package cn.com.cifi.mars.web.action.operateplan;
import static java.util.stream.Collectors.toList;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.com.cifi.mars.entity.*;
import cn.com.cifi.mars.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.com.cifi.mars.bean.bo.SysLogBO;
import cn.com.cifi.mars.bean.dto.ProjectByStagesDto;
import cn.com.cifi.mars.bean.dto.SupplyPlanValueDetailDto;
import cn.com.cifi.mars.bean.dto.SupplyPlanVersionDto;
import cn.com.cifi.mars.bean.vo.supply.BaseExcelValueVO;
import cn.com.cifi.mars.bean.vo.supply.BaseValueVO;
import cn.com.cifi.mars.bean.vo.supply.MonthExcelValueVO;
import cn.com.cifi.mars.bean.vo.supply.MonthValueVO;
import cn.com.cifi.mars.bean.vo.supply.ProjectBaseExcelValueVO;
import cn.com.cifi.mars.bean.vo.supply.ProjectExcelValueVO;
import cn.com.cifi.mars.bean.vo.supply.ProjectMonthExcelValueVO;
import cn.com.cifi.mars.bean.vo.supply.ProjectMonthValueVO;
import cn.com.cifi.mars.bean.vo.supply.ProjectValueVO;
import cn.com.cifi.mars.bean.vo.supply.ProjectYearExcelValueVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyConfirmDetailVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyConfirmExcelVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyConfirmMonthDetailVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyConfirmProjectMonthValueVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyConfirmProjectValueVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyConfirmVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyPlanExcelVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyPlanOverAllValueDataVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyPlanVersionCompareVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyPlanVersionDataVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyPlanVersionsVO;
import cn.com.cifi.mars.bean.vo.supply.SupplyYearValueVO;
import cn.com.cifi.mars.bean.vo.supply.YearExcelValueVO;
import cn.com.cifi.mars.bean.vo.sys.rsp.GroupUserVo;
import cn.com.cifi.mars.common.base.BaseAction;
import cn.com.cifi.mars.common.bean.R;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.common.redis.RedisTemplateUtil;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.HrOrgTypeEunm;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.IsSuccessEnum;
import cn.com.cifi.mars.constant.LogEventEnum;
import cn.com.cifi.mars.constant.LogSrcEnum;
import cn.com.cifi.mars.constant.LogTypeEnum;
import cn.com.cifi.mars.constant.MonthEnum;
import cn.com.cifi.mars.constant.NumberEnum;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.SalyTypeEnum;
import cn.com.cifi.mars.constant.SupplyEnum;
import cn.com.cifi.mars.constant.VersionAttrEnum;
import cn.com.cifi.mars.constant.VersionIdentifyEnum;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.entity.common.ProjectByStages;
import cn.com.cifi.mars.schedled.SupplyPlanTasks;
import cn.com.cifi.mars.util.DateUtils;
import cn.com.cifi.mars.util.EmptyUtils;
import cn.com.cifi.mars.util.LocalDateTimeUtils;
import cn.com.cifi.mars.util.NumberUtils;
import cn.com.cifi.mars.util.OverallSupplyReportTemplate;
import cn.com.cifi.mars.util.ReportUtils;
import cn.com.cifi.mars.util.StrUtils;
import cn.com.cifi.mars.util.SupplyConfirmTemplate;
import cn.com.cifi.mars.util.WebUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @Description：供货计划
 * @author：yyd
 * @date：2020年1月6日 上午10:49:14
 */
@Slf4j
@RestController
public class SupplyPlanController extends BaseAction implements ISupplyPlanController {
	
	@Autowired
	private SupplyPlanVersionService supplyPlanVersionService;
	
	@Autowired
	private SupplyPlanVersionDetailService supplyPlanVersionDetailService;
	
	@Autowired
	private SupplyPlanExportService supplyPlanExportService;
	
	@Autowired
	private ProjectService projectService;
	
	@Autowired
	private SysLogService sysLogService;
	
	@Autowired
	private PriceVersionService priceVersionService;
	
	@Autowired
	private SupplyConfirmRecordService supplyConfirmRecordService;
	
	@Autowired
	private SupplyConfirmRecordDetailService supplyConfirmRecordDetailService;
	
	@Autowired
	private IdmUserService idmUserService;
	
	@Autowired
	private SupplyPlanVersionCompareService supplyPlanVersionCompareService;
	
	@Autowired
	private DmDmSupplyConfirmReportService dmDmSupplyConfirmReportService;
	
	@Autowired
	private SupplyPlanTasks supplyPlanTasks;
	
	@Autowired
	private StageService stageService;
	
	@Autowired
    private RedisTemplateUtil redisTemplateUtil;

	@Autowired
	private StagePartNersService stagePartNersService;
	
	@Override
	public R createSupplyPlanVersion(String apiVersion, String priceVersionId,String versionType) {
		supplyPlanVersionService.createSupplyPlanVersion(priceVersionId,versionType,Constants.SYS);
		return ok();
	}
	
	@Override
	public R finalizeCreateSupplyPlanVersion(String apiVersion, String priceVersionId, String versionType) {
		String alias = getOperator().getAlias();
		supplyPlanVersionService.finalizeCreateSupplyPlanVersion(priceVersionId, versionType, alias);
		return ok();
	}
	
	@Override
	public R<String> newestVersionStage(String apiVersion, String projectFid) {
		return ok(supplyPlanVersionService.queryNewestVersionStage(projectFid));
	}
	
	@Override
	public R<List<SupplyPlanVersionsVO>> versionList(String apiVersion,String projectFId, String versionType) {
		List<SupplyPlanVersionsVO> list = supplyPlanVersionService.queryVersions(projectFId,versionType);
		if(CollectionUtils.isEmpty(list)) {
			if(versionType.equals(VersionTypeEunm.BUDGET.getKey())) {
				throw new MsgException(CodeEnum.NOT_EXISTENT_BUDGET_VERSION);
			}else {
				throw new MsgException(CodeEnum.NOT_EXISTENT_VERSION);
			}
		}
		return ok(list);
	}
	
	@Override
	public R<List<SupplyPlanVersionDataVO>> getVersionData(String apiVersion,String versionId,String type,String code) {
		List<SupplyPlanVersionDataVO> dataList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDetail> allList = Collections.synchronizedList(new ArrayList<>());
		String versionType = supplyPlanVersionService.queryVersionType(versionId);
		if(StrUtils.isNotEmpty(code)) {
			 allList = supplyPlanVersionDetailService.queryByVersionId(versionId);
		}
		//数据汇总
		List<SupplyPlanVersionDetail> list = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(allList,versionType,versionId,code,"","");
		if(CollectionUtils.isNotEmpty(list)) {
			list.forEach(x->{
				SupplyPlanVersionDataVO vo = new SupplyPlanVersionDataVO();
				vo.setId(x.getId());
				vo.setCode(x.getOrgCode());
				vo.setName(x.getOrgName());
				vo.setType(x.getType());
				vo.setPid(x.getPid());
				vo.setProProductCode(x.getProProductCode());
				vo.setProProductName(x.getProProductType());
				vo.setIsSupply(x.getIsSupply());
				vo.setIsParking(x.getIsParking());
				vo.setIsDelay(x.getIsDelay());
				//计划：套数、面积、均价、货值、供货日期
				vo.setNum(EmptyUtils.handleNumNullValue(x.getNums()));
				vo.setSaleArea(EmptyUtils.handleAreaNullValue(x.getSaleArea()));
				vo.setAvgPrice(EmptyUtils.handleAvgNullValue2(x.getAvgPrice()));
				vo.setPrice(EmptyUtils.handlePriceNullValue2(x.getPrice()));
				vo.setSupplyTime(x.getSupplyDate());
				//供货实际：套数、面积、均价、货值、供货日期、达成率
				vo.setActualNum(EmptyUtils.handleNumNullValue(x.getNumsActual()));
				vo.setActualArea(EmptyUtils.handleAreaNullValue(x.getAreaActual()));
				vo.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(x.getAvgPriceActual()));
				vo.setActualPrice(EmptyUtils.handlePriceNullValue2(x.getPriceActual()));
				vo.setActualSupplyDate(x.getSupplyTimeVirtual() == null ?  x.getSupplyDateActual() : x.getSupplyTimeVirtual());
				vo.setAchievingRate(x.getValueAchievingRate());
				dataList.add(vo);
			});
		}
		//层级数据排序
		List<SupplyPlanVersionDataVO> resList = versionDetailSort(dataList);
		saveLog("供货计划","版本数据信息","版本数据信息查询");
		return ok(resList);
	}
	
	private List<SupplyPlanVersionDataVO> versionDetailSort(List<SupplyPlanVersionDataVO> dataList) {
		List<SupplyPlanVersionDataVO> resList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDataVO> groupList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDataVO> batchList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDataVO> productList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanVersionDataVO> houseList = Collections.synchronizedList(new ArrayList<>());
		dataList.forEach(x->{
			String typeTemp = x.getType();
			if(typeTemp.equals(OrgTypeEunm.ORG_GROUP.getKey())){
                groupList.add(x);
            }else if(typeTemp.equals(OrgTypeEunm.ORG_BATCH.getKey())){
                batchList.add(x);
            }else if(typeTemp.equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
                productList.add(x);
            }else if(typeTemp.equals(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())){
                houseList.add(x);
            }else {
            	resList.add(x);
            }
		});
		
		//组团
		if(CollectionUtils.isNotEmpty(groupList)){
             groupList.sort((a, b) -> {
                 String aName = a.getName();
		         String bName = b.getName();
		         String[] aStr = aName.split("组团");
		         String[] bStr = bName.split("组团");
		         if(aStr[0].equals(Constants.PARKING_NAME)) {
		             aStr[0] = Constants.GROUP_NUM;
		         }
		         if(bStr[0].equals(Constants.PARKING_NAME)){
		             bStr[0] = Constants.GROUP_NUM;
		         }
		         String aValue = NumberEnum.getKeyByValue(aStr[0]);
		         String bValue = NumberEnum.getKeyByValue(bStr[0]);
		         
		         if(StrUtils.isEmpty(aValue)) {
 		        	return 1; 
 		         }else if(StrUtils.isEmpty(bValue)) {
 		        	 return -1;
 		         }else if(StrUtils.isNotEmpty(aValue) && StrUtils.isNotEmpty(bValue)) {
 		        	 return Integer.valueOf(aValue) - Integer.valueOf(bValue);
 		         }
	     		 return 0;
             });
             resList.addAll(groupList);
         }
		//批次
		 if(CollectionUtils.isNotEmpty(batchList)) {
             batchList.sort((a, b) -> {
                 String aName = a.getName();
                 String bName = b.getName();
                 String[] aStr = aName.split("批次");
                 String[] bStr = bName.split("批次");
                 String aValue = NumberEnum.getKeyByValue(aStr[0]);
                 String bValue = NumberEnum.getKeyByValue(bStr[0]);
                 if(StrUtils.isEmpty(aValue)) {
  		        	return 1; 
  		         }else if(StrUtils.isEmpty(bValue)) {
  		        	 return -1;
  		         }else if(StrUtils.isNotEmpty(aValue) && StrUtils.isNotEmpty(bValue)) {
  		        	 return Integer.valueOf(aValue) - Integer.valueOf(bValue);
  		         }
 	     		 return 0;
                 
             });
             resList.addAll(batchList);
         }
		 
		 //产品构成
		 if(CollectionUtils.isNotEmpty(productList)) {
             productList.sort((a, b) -> {
                 String aValue = a.getCode();
                 String bValue = b.getCode();
                 if(StrUtils.isEmpty(aValue)) {
   		        	return 1; 
   		         }else if(StrUtils.isEmpty(bValue)) {
   		        	 return -1;
   		         }else if(StrUtils.isNotEmpty(aValue) && StrUtils.isNotEmpty(bValue)) {
   		        	 return Integer.valueOf(aValue) - Integer.valueOf(bValue);
   		         }
  	     		 return 0;
             });
             resList.addAll(productList);
         }
		 
		 resList.addAll(houseList);
		 
		return resList;
	}
	
	@Override
	public R isExistBudgetVersion(String apiVersion, String projectFid) {
		boolean isExistBudgetVersion = supplyPlanVersionService.isExistBudgetVersion(projectFid);
		return ok(isExistBudgetVersion);
	}
	
	@Override
	public R createSupplyBudgetVersion(String apiVersion, String projectFid) {
		String alias = getOperator().getAlias();
		supplyPlanVersionService.createSupplyBudgetVersion(projectFid,alias);
		return ok();
	}
	
	@Override
	public R setAssessmentTag(String apiVersion, String versionId,String projectFid) {
		supplyPlanVersionService.setAssessmentTag(versionId,projectFid);
		saveLog("供货计划","考核版标签","设置投资版考核版标签");
		return ok();
	}
	
	@Override
	public R updateAssessmentTag(String apiVersion, String versionId,String projectFid) {
		supplyPlanVersionService.updateAssessmentTag(versionId,projectFid);
		saveLog("供货计划","考核版标签","修改投资版考核版标签");
		return ok();
	}
	
	@Override
	public R isNeedSpplyConfirm(String apiVersion, String projectId) {
		supplyPlanVersionService.isNeedSpplyConfirm(projectId);
		return ok();
	}
	
	@Override
	public R isShowSupplyConfirm(String apiVersion, String projectId,String versionDate) {
		boolean isShow = true;
		String affiliationMonth = supplyPlanVersionService.getAffiliationMonth(versionDate);
		if(supplyPlanVersionService.isBetweenComfirmTime()) {
			//历史月份不显示供货确认
			LocalDateTime versionTime = LocalDateTimeUtils.toLocalDateTime(versionDate);
			LocalDateTime affiliationMonthTime = LocalDateTimeUtils.toLocalDateTime(affiliationMonth);
			if(versionTime.isBefore(affiliationMonthTime)) {
				isShow = false;
			}else {
				//已确认不显示
				SupplyConfirmRecord record = supplyConfirmRecordService.queryByProjectId(projectId,affiliationMonth);
				if(record != null) {
					isShow = false;
				}
			}
		}else {
			isShow = false;
		}
		return ok(isShow);
	}
	
	@Override
	public R supplyConfirmDetail(String apiVersion,String projectId,String versionDate) {
		List<SupplyConfirmDetailVO> resList = Collections.synchronizedList(new ArrayList<>());
		//版本归属月份
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		String affiliationMonth = "";
		String showMonth = "";
		if(LocalDateTimeUtils.isSameMonth(versionDate)) {
			affiliationMonth = supplyPlanVersionService.getAffiliationMonth(versionDate);
			LocalDateTime now = LocalDateTime.now();
			String comfirmTime  = supplyPlanVersionService.getComfirmTime();
			LocalDateTime endComfirmTime = LocalDateTimeUtils.strToDate(comfirmTime, df);
			LocalDateTime beginTimeTemp = endComfirmTime.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
			LocalDateTime beginComfirmTime = beginTimeTemp.with(TemporalAdjusters.lastDayOfMonth()).minusDays(1);
			if(now.isBefore(beginComfirmTime)) {
				showMonth = LocalDateTimeUtils.getLastMonth(versionDate);
			}else {
				showMonth = affiliationMonth;
			}
		}else {
			affiliationMonth = versionDate;
			showMonth = LocalDateTimeUtils.getLastMonth(versionDate);
		}
    	LocalDateTime time = LocalDateTimeUtils.parseDate(showMonth+"-01 00:00:00",df);
    	int monthNum = time.getMonthValue();
    	int year = time.getYear();
    	//详情页面展示的月份
    	List<String> months = LocalDateTimeUtils.getSupplyConfirmDetailMonths(year,monthNum);
    	//获取版本信息
    	List<SupplyPlanVersion> supplyPlanVersionList = supplyPlanVersionService.selectNewestDynamicVersion(projectId,affiliationMonth);
    	if(CollectionUtils.isEmpty(supplyPlanVersionList)) {
    		throw new MsgException(CodeEnum.NOT_EXIST_SUPPLY_DYNAMIC_VERSION);
    	}
    	//获取项目信息
    	MdmProject project = projectService.selectByProjectId(projectId,IsDeleteEnum.NO.getKey());
    	
    	SupplyConfirmProjectValueVO projectTempVO = new SupplyConfirmProjectValueVO();
    	for(SupplyPlanVersion supplyPlanVersion : supplyPlanVersionList) {
    		SupplyConfirmDetailVO supplyConfirmDetailVO = initSupplyConfirmDetailVo();
    		String versionId = supplyPlanVersion.getId();
    		String versionName = prepareVersionName(supplyPlanVersion);
    		SupplyPlanVersionDto version = supplyPlanVersionService.selectVersionData(versionId);
    		//年度
    		SupplyPlanValueDetailDto yearData = supplyConfirmRecordDetailService.prepareProjectYearData(versionId,year);
    		supplyConfirmDetailVO.setId(version.getProjectfId());
    		supplyConfirmDetailVO.setCode(version.getStageCode());
    		supplyConfirmDetailVO.setName(version.getStageName()+"("+versionName+")");
    		supplyConfirmDetailVO.setType(OrgTypeEunm.ORG_STAGE.getKey());
    		supplyConfirmDetailVO.setPid(project.getProjectId());
    		supplyConfirmDetailVO.setYear(year+"");
    		if(yearData != null) {
        		supplyConfirmDetailVO.setYearNum(EmptyUtils.handleNumNullValue(yearData.getRoomNum()+"/"+yearData.getParkingNum()));
        		supplyConfirmDetailVO.setYearArea(EmptyUtils.handleAreaNullValue(yearData.getArea()));
        		supplyConfirmDetailVO.setYearAvgPrice(EmptyUtils.handleAvgNullValue(NumberUtils.divide(yearData.getHouseCommodityValue(),yearData.getArea(),2)+"/"+ NumberUtils.divide(yearData.getNotCommodityValue(),yearData.getParkingNum()==null?null:new BigDecimal(yearData.getParkingNum()),2)));
        		supplyConfirmDetailVO.setYearPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(3,yearData.getHouseCommodityValue(),yearData.getNotCommodityValue())+"/"+yearData.getHouseCommodityValue()+"/"+yearData.getNotCommodityValue()));
        		supplyConfirmDetailVO.setYearActualNum(EmptyUtils.handleNumNullValue(yearData.getRoomNumActual()+"/"+yearData.getParkingNumActual()));
				supplyConfirmDetailVO.setYearActualArea(EmptyUtils.handleAreaNullValue(yearData.getAreaActual()));
				supplyConfirmDetailVO.setYearActualAveragePrice(EmptyUtils.handleAvgNullValue(NumberUtils.divide(yearData.getHouseCommodityValueActual(),yearData.getAreaActual(),2)+"/"+ NumberUtils.divide(yearData.getNotCommodityValueActual(),yearData.getParkingNumActual()==null?null:new BigDecimal(yearData.getParkingNumActual()),2)));
				supplyConfirmDetailVO.setYearActualPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(3,yearData.getHouseCommodityValueActual(),yearData.getNotCommodityValueActual())+"/"+yearData.getHouseCommodityValueActual()+"/"+yearData.getNotCommodityValueActual()));
        		//达成率=实际货值/计划货值
    			BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,yearData.getHouseCommodityValueActual(),yearData.getNotCommodityValueActual());
    			BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,yearData.getHouseCommodityValue(),yearData.getNotCommodityValue());
        		if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
        			supplyConfirmDetailVO.setAchievingRate("-");
        		}else {
        			supplyConfirmDetailVO.setAchievingRate(NumberUtils.divide(sumPriceActual,sumPrice,4)==null?"":NumberUtils.divide(sumPriceActual,sumPrice,4)+"");
        		}
        		//汇总月度数据到项目层级
        		projectTempVO.setRoomNum(NumberUtils.intADD(projectTempVO.getRoomNum(),yearData.getRoomNum()));
        		projectTempVO.setParkingNum(NumberUtils.intADD(projectTempVO.getParkingNum(),yearData.getParkingNum()));
        		projectTempVO.setSaleArea(NumberUtils.BigDecimalADD(2, projectTempVO.getSaleArea(), yearData.getArea()));
        		projectTempVO.setHousePrice(NumberUtils.BigDecimalADD(3,projectTempVO.getHousePrice(),yearData.getHouseCommodityValue()));
        		projectTempVO.setParkingPrice(NumberUtils.BigDecimalADD(3,projectTempVO.getParkingPrice(),yearData.getNotCommodityValue()));
        		projectTempVO.setActualRoomNum(NumberUtils.intADD(projectTempVO.getActualRoomNum(),yearData.getRoomNumActual()));
        		projectTempVO.setActualParkingNum(NumberUtils.intADD(projectTempVO.getActualParkingNum(),yearData.getParkingNumActual()));
        		projectTempVO.setActualArea(NumberUtils.BigDecimalADD(2,projectTempVO.getActualArea(),yearData.getAreaActual()));
        		projectTempVO.setActualHousePrice(NumberUtils.BigDecimalADD(3,projectTempVO.getActualHousePrice(),yearData.getHouseCommodityValueActual()));
        		projectTempVO.setActualParkingPrice(NumberUtils.BigDecimalADD(3,projectTempVO.getActualParkingPrice(),yearData.getNotCommodityValueActual()));
    		}
    		//月度
    		List<SupplyConfirmMonthDetailVO> monthDataList = Collections.synchronizedList(new ArrayList<>());
    		for(String month : months) {
    			SupplyConfirmMonthDetailVO monthVo = initSupplyConfirmMonthDetailVO();
    			SupplyPlanValueDetailDto monthData = supplyConfirmRecordDetailService.prepareProjectMonthData(versionId,month);
    			if(monthData != null) {
    				monthVo.setNum(EmptyUtils.handleNumNullValue(monthData.getRoomNum()+"/"+monthData.getParkingNum()));
        			monthVo.setSaleArea(EmptyUtils.handleAreaNullValue(monthData.getArea()));
        			monthVo.setAvgPrice(EmptyUtils.handleAvgNullValue(NumberUtils.divide(monthData.getHouseCommodityValue(),monthData.getArea(),2)+"/"+ NumberUtils.divide(monthData.getNotCommodityValue(),monthData.getParkingNum()==null?null:new BigDecimal(monthData.getParkingNum()),2)));
        			monthVo.setPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(3,monthData.getHouseCommodityValue(),monthData.getNotCommodityValue())+"/"+monthData.getHouseCommodityValue()+"/"+monthData.getNotCommodityValue()));
        			//汇总月度数据到项目层级
        			List<SupplyConfirmProjectMonthValueVO> monthValueVO = projectTempVO.getMonthValue(months);
        			for(SupplyConfirmProjectMonthValueVO vo : monthValueVO) {
        				if(month.equals(vo.getName())) {
        					vo.setRoomNum(NumberUtils.intADD(vo.getRoomNum(),monthData.getRoomNum()));
        					vo.setParkingNum(NumberUtils.intADD(vo.getParkingNum(),monthData.getParkingNum()));
        					vo.setSaleArea(NumberUtils.BigDecimalADD(2,vo.getSaleArea(),monthData.getArea()));
        					vo.setHousePrice(NumberUtils.BigDecimalADD(3,vo.getHousePrice(),monthData.getHouseCommodityValue()));
        					vo.setParkingPrice(NumberUtils.BigDecimalADD(3,vo.getParkingPrice(),monthData.getNotCommodityValue()));
        				}
        			}
    			}
    			monthVo.setMonth(month);
    			monthDataList.add(monthVo);
    		}
    		supplyConfirmDetailVO.setMonthData(monthDataList);
    		resList.add(supplyConfirmDetailVO);
    	}
    	
    	//添加项目层级
    	//获取供货确认记录信息
    	SupplyConfirmRecord record = supplyConfirmRecordService.queryByProjectId(projectId,affiliationMonth);
    	
    	SupplyConfirmDetailVO supplyConfirmDetailVO = new SupplyConfirmDetailVO();
    	supplyConfirmDetailVO.setId(project.getProjectId());
		supplyConfirmDetailVO.setCode(project.getProjectCode());
		supplyConfirmDetailVO.setName(project.getProjectName());
		supplyConfirmDetailVO.setType(OrgTypeEunm.ORG_PRODUCTF.getKey());
		supplyConfirmDetailVO.setPid(Constants.ROOT_NODE_PID);
		supplyConfirmDetailVO.setYear(year+"");
		if(record != null) {
			if(record.getConfirmStatus() != null && record.getConfirmStatus().intValue() == 1) {
				supplyConfirmDetailVO.setConfirmStatus(record.getConfirmStatus());
			}else {
				supplyConfirmDetailVO.setConfirmStatus(0);
			}
			if(StrUtils.isNotEmpty(record.getConfirmUserId())) {
				supplyConfirmDetailVO.setConfirmBy(idmUserService.getByAlias(record.getConfirmUserId()).getUsercn());
			}else {
				supplyConfirmDetailVO.setConfirmBy(record.getPrincipal());
			}
			if(record.getConfirmTime() != null) {
				supplyConfirmDetailVO.setConfirmTime(LocalDateTimeUtils.formatTime(record.getConfirmTime(),"yyyy-MM-dd HH:mm"));
			}
		}else {
			supplyConfirmDetailVO.setConfirmBy(getProjectPmUser(project.getProjectId()));
		}
		supplyConfirmDetailVO.setYearNum(EmptyUtils.handleNumNullValue(projectTempVO.getRoomNum()+"/"+projectTempVO.getParkingNum()));
		supplyConfirmDetailVO.setYearArea(EmptyUtils.handleAreaNullValue(projectTempVO.getSaleArea()== null ? BigDecimal.ZERO : projectTempVO.getSaleArea()));
		supplyConfirmDetailVO.setYearAvgPrice(EmptyUtils.handleAvgNullValue(NumberUtils.divide(projectTempVO.getHousePrice(),projectTempVO.getSaleArea(),2)+"/"+ NumberUtils.divide(projectTempVO.getParkingPrice(),projectTempVO.getParkingNum()==null?null:new BigDecimal(projectTempVO.getParkingNum()),2)));
		supplyConfirmDetailVO.setYearPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(3,projectTempVO.getHousePrice(),projectTempVO.getParkingPrice())+"/"+projectTempVO.getHousePrice()+"/"+projectTempVO.getParkingPrice()));
		supplyConfirmDetailVO.setYearActualNum(EmptyUtils.handleNumNullValue(projectTempVO.getActualRoomNum()+"/"+projectTempVO.getActualParkingNum()));
		supplyConfirmDetailVO.setYearActualArea(EmptyUtils.handleAreaNullValue(projectTempVO.getActualArea()== null ? BigDecimal.ZERO : projectTempVO.getActualArea()));
		supplyConfirmDetailVO.setYearActualAveragePrice(EmptyUtils.handleAvgNullValue(NumberUtils.divide(projectTempVO.getActualHousePrice(),projectTempVO.getActualArea(),2)+"/"+ NumberUtils.divide(projectTempVO.getActualParkingPrice(),projectTempVO.getActualParkingNum()==null?null:new BigDecimal(projectTempVO.getActualParkingNum()),2)));
		supplyConfirmDetailVO.setYearActualPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(3,projectTempVO.getActualHousePrice(),projectTempVO.getActualParkingPrice())+"/"+projectTempVO.getActualHousePrice()+"/"+projectTempVO.getActualParkingPrice()));
		//达成率=实际货值/计划货值
		BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,projectTempVO.getActualHousePrice(),projectTempVO.getActualParkingPrice());
		BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,projectTempVO.getHousePrice(),projectTempVO.getParkingPrice());
		if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
			supplyConfirmDetailVO.setAchievingRate("-");
		}else {
			supplyConfirmDetailVO.setAchievingRate(NumberUtils.divide(sumPriceActual,sumPrice,4)==null?null:NumberUtils.divide(sumPriceActual,sumPrice,4)+"");
		}
		
		List<SupplyConfirmMonthDetailVO> monthDataList = Collections.synchronizedList(new ArrayList<>());
		for(String month : months) {
			SupplyConfirmMonthDetailVO monthVo = new SupplyConfirmMonthDetailVO();
			monthVo.setMonth(month);
			for(SupplyConfirmProjectMonthValueVO vo : projectTempVO.getMonthValue(months)) {
				if(month.equals(vo.getName())) {
					monthVo.setNum(EmptyUtils.handleNumNullValue(vo.getRoomNum()+"/"+vo.getParkingNum()));
        			monthVo.setSaleArea(EmptyUtils.handleAreaNullValue(vo.getSaleArea() == null ? BigDecimal.ZERO : vo.getSaleArea()));
        			monthVo.setAvgPrice(EmptyUtils.handleAvgNullValue(NumberUtils.divide(vo.getHousePrice(),vo.getSaleArea(),2)+"/"+ NumberUtils.divide(vo.getParkingPrice(),vo.getParkingNum()==null?null:new BigDecimal(vo.getParkingNum()),2)));
        			monthVo.setPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(3,vo.getHousePrice(),vo.getParkingPrice())+"/"+vo.getHousePrice()+"/"+vo.getParkingPrice()));
				}
			}
			monthDataList.add(monthVo);
		}
		supplyConfirmDetailVO.setMonthData(monthDataList);
		resList.add(supplyConfirmDetailVO);
		//分期排序
		List<SupplyConfirmDetailVO> lastList = supplyConfirmStageSort(resList);
		//saveLog("供货计划","查看供货确认","查询项目供货确认详情");
		return ok(lastList);
	}

	private SupplyConfirmMonthDetailVO initSupplyConfirmMonthDetailVO() {
		SupplyConfirmMonthDetailVO monthVo = new SupplyConfirmMonthDetailVO();
		monthVo.setNum("0 / 0");
		monthVo.setSaleArea("0.00");
		monthVo.setAvgPrice("0 / 0");
		monthVo.setPrice("0 / 0 / 0");
		return monthVo;
	}

	private SupplyConfirmDetailVO initSupplyConfirmDetailVo() {
		SupplyConfirmDetailVO supplyConfirmDetailVO = new SupplyConfirmDetailVO();
		supplyConfirmDetailVO.setYearNum("0");
		supplyConfirmDetailVO.setYearArea("0.00");
		supplyConfirmDetailVO.setYearAvgPrice("0");
		supplyConfirmDetailVO.setYearPrice("0");
		supplyConfirmDetailVO.setYearActualNum("0");
		supplyConfirmDetailVO.setYearActualArea("0.00");
		supplyConfirmDetailVO.setYearActualAveragePrice("0");
		supplyConfirmDetailVO.setYearActualPrice("0");
		return supplyConfirmDetailVO;
	}

	private List<SupplyConfirmDetailVO> supplyConfirmStageSort(List<SupplyConfirmDetailVO> resList) {
		List<SupplyConfirmDetailVO> lastList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyConfirmDetailVO> sList = Collections.synchronizedList(new ArrayList<>());
		resList.forEach(x->{
			String typeTemp = x.getType();
			if(typeTemp.equals(OrgTypeEunm.ORG_STAGE.getKey())){
				sList.add(x);
            }else {
            	lastList.add(x);
            }
		});
		//排序
		if(CollectionUtils.isNotEmpty(sList)){
			List<SupplyConfirmDetailVO> sortList = sList.parallelStream().sorted((a, b) -> {
			    //分期
			    String aStageName = StrUtils.nvl(a.getName());
			    String bStageName = StrUtils.nvl(b.getName());
			    if (!aStageName.equals(bStageName)) {
			    	return ReportUtils.compareStrStartedChinaNum(aStageName, bStageName);
			    }
			    return 0;
			}).collect(Collectors.toList());
			
			lastList.addAll(sortList);
         }
		return lastList;
	}
	
	@Override
	public R supplyConfirmDetailTwo(String apiVersion,String projectName,Integer status,String versionDate) {
		log.info("###############集团级供货确认表   Start: "+ LocalDateTime.now());
//		List<SupplyConfirmDetailVO> resList = prepareGroupSupplyConfirmDetail(projectName, status, versionDate);
		
		List<SupplyConfirmDetailVO> resList = getGroupSupplyConfirmDetail(projectName, status, versionDate);
		//分期排序
		List<SupplyConfirmDetailVO> lastList = supplyConfirmStageSort(resList);
		log.info("###############集团级供货确认表   End: "+ LocalDateTime.now());
		return ok(lastList);
	}
	
	@Override
	public void supplyConfirmExport(String apiVersion, HttpServletRequest request, HttpServletResponse response,
			String projectName, Integer status, String versionDate) {
		String affiliationMonth = "";
		if(LocalDateTimeUtils.isSameMonth(versionDate)) {
			if(redisTemplateUtil.get(Constants.RedisConfirmDate) == null) {
				affiliationMonth = supplyPlanVersionService.getAffiliationMonth(versionDate);
			}else {
				affiliationMonth = (String) redisTemplateUtil.get(Constants.RedisConfirmDate);
			}
		}else {
			affiliationMonth= versionDate;
		}
		//获取数据权限
    	List<String> projectIds = prepareUserDataPermission();
    	//获取数据
    	List<DmDmSupplyConfirmReport> list = dmDmSupplyConfirmReportService.queryList(affiliationMonth,projectIds,projectName,status);
		//项目父级
    	List<ProjectByStages> allOrgList = supplyPlanVersionService.selectProjectParentList();
    	
    	List<SupplyConfirmExcelVO> allList = Collections.synchronizedList(new ArrayList<>());
    	List<SupplyConfirmExcelVO> stageList = Collections.synchronizedList(new ArrayList<>());
    	if(CollectionUtils.isNotEmpty(list)) {
    		for(DmDmSupplyConfirmReport report : list) {
    			String proId = report.getProjectId();
        		String proCode = report.getProjectCode();
        		String proName = report.getProjectName();
        		String stageId = report.getProjectfId();
        		String stageCode = report.getProjectfCode();
        		String stageName = report.getProjectfName();
        		String versionName = report.getVersionName();
        		ProjectByStages project = getOrgData(proId,allOrgList);
        		if(project != null) {
        			ProjectByStages city = getOrgData(project.getParentOrgid(),allOrgList);
        			if(city != null) {
        				ProjectByStages businessDivisionObj = getOrgData(city.getParentOrgid(),allOrgList);
        				SupplyConfirmExcelVO excelVo = new SupplyConfirmExcelVO();
                		excelVo.setId(stageId);
                		excelVo.setCode(stageCode);
                		excelVo.setName(stageName);
                		excelVo.setPid(proId);
                		excelVo.setType(OrgTypeEunm.ORG_STAGE.getKey());
                		excelVo.setStageName(stageName);
                		excelVo.setVersionName(versionName);
                		excelVo.setProjectCode(proCode);
                		excelVo.setProjectName(proName);
                		excelVo.setCityName(city.getOrgname());
                		if(businessDivisionObj != null) {
                			excelVo.setAreaName(businessDivisionObj.getOrgname());
                		}
                		stageList.add(excelVo);
        			}
        		}
    		}
    	}
    	List<SupplyConfirmExcelVO> proList = Collections.synchronizedList(new ArrayList<>());
    	if(CollectionUtils.isNotEmpty(stageList)) {
    		for(SupplyConfirmExcelVO vo : stageList) {
    			SupplyConfirmExcelVO excelVo = new SupplyConfirmExcelVO();
    			ProjectByStages project = getOrgData(vo.getPid(),allOrgList);
    			if(project != null) {
    				ProjectByStages city = getOrgData(project.getParentOrgid(),allOrgList);
    				if(city != null) {
    					ProjectByStages businessDivisionObj = getOrgData(city.getParentOrgid(),allOrgList);
            			excelVo.setId(project.getOrgdepid());
                		excelVo.setName(project.getOrgname());
                		excelVo.setPid(city.getOrgdepid());
                		excelVo.setType(OrgTypeEunm.ORG_PRODUCTF.getKey());
                		excelVo.setProjectCode(vo.getProjectCode());
                		excelVo.setProjectName(vo.getProjectName());
                		excelVo.setCityName(city.getOrgname());
                		if(businessDivisionObj != null) {
                			excelVo.setAreaName(businessDivisionObj.getOrgname());
                		}
                		DmDmSupplyConfirmReport report = getDmDmSupplyConfirmReport(list,project.getOrgdepid());
            			if(report != null) {
            				if(report.getConfirmStatus() != null) {
            					if(report.getConfirmStatus().intValue() == 1) {
            						excelVo.setConfirmStatus("已确认");
            					}else {
            						excelVo.setConfirmStatus("未确认");
            					}
            				}else {
            					excelVo.setConfirmStatus("未确认");
            				}
            				excelVo.setConfirmUser(StrUtils.isEmpty(report.getConfirmUserName()) ? report.getPrincipal() : report.getConfirmUserName());
                    		if(report.getConfirmTime() != null) {
                    			excelVo.setConfirmTime(LocalDateTimeUtils.formatTime(report.getConfirmTime(),"yyyy-MM-dd HH:mm"));
                    		}
            			}
                		proList.add(excelVo);
    				}
    			}
    		}
    	}
    	allList.addAll(stageList);
    	allList.addAll(proList);
    	
    	//去重
    	List<SupplyConfirmExcelVO> uniqList = allList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SupplyConfirmExcelVO::getId))), ArrayList::new)
        );
    		
		List<SupplyConfirmExcelVO> sortList = sortSupplyConfirmList(uniqList);
		
		SupplyConfirmTemplate reportTemplate = new SupplyConfirmTemplate(versionDate);
		reportTemplate.appendRows(sortList);
        try (OutputStream outputStream = response.getOutputStream()){
        	response.setContentType("application/vnd.ms-excel");
        	response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode("供货确认表".concat(versionDate.replace("-", "")).concat("-").concat(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH"))).concat(".xls"), "utf-8"));
        	reportTemplate.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            log.error("###### errorMsg: ", e);
        }
	}
	
	private List<SupplyConfirmExcelVO> sortSupplyConfirmList(List<SupplyConfirmExcelVO> resList) {
		return resList.parallelStream().sorted((a, b) -> {
		    //区域
			String aRegionName = StrUtils.nvl(a.getAreaName());
		    String bRegionName = StrUtils.nvl(b.getAreaName());
		    if (!aRegionName.equals(bRegionName)) {
		        return aRegionName.compareTo(bRegionName);
		    }
		    //城市公司
		    String aCityName = StrUtils.nvl(a.getCityName());
		    String bCityName = StrUtils.nvl(b.getCityName());
		    if (!aCityName.equals(bCityName)) {
		        return aCityName.compareTo(bCityName);
		    }
		    //项目
		    String aProjectName = StrUtils.nvl(a.getProjectName());
		    String bProjectName = StrUtils.nvl(b.getProjectName());
		    if (!aProjectName.equals(bProjectName)) {
		        return aProjectName.compareTo(bProjectName);
		    }
		    //分期
		    String aProjectfName = StrUtils.nvl(a.getStageName());
		    String bProjectfName = StrUtils.nvl(b.getStageName());
		    if (!aProjectfName.equals(bProjectfName)) {
		    	return ReportUtils.compareStrStartedChinaNum(aProjectfName, bProjectfName);
		    }
		    return 0;
		}).collect(Collectors.toList());
	}

	private List<SupplyConfirmDetailVO> getGroupSupplyConfirmDetail(String projectName,Integer status,String versionDate) {
		List<SupplyConfirmDetailVO> resList = Collections.synchronizedList(new ArrayList<>());
		String affiliationMonth = "";
		String showMonth = "";
		if(LocalDateTimeUtils.isSameMonth(versionDate)) {
			if(redisTemplateUtil.get(Constants.RedisConfirmDate) == null) {
				affiliationMonth = supplyPlanVersionService.getAffiliationMonth(versionDate);
			}else {
				affiliationMonth = (String) redisTemplateUtil.get(Constants.RedisConfirmDate);
			}
			if(redisTemplateUtil.get(Constants.RedisConfirmShowDate) == null) {
				showMonth = prepareConfirmShowDate(versionDate, affiliationMonth);
			}else {
				showMonth = (String) redisTemplateUtil.get(Constants.RedisConfirmShowDate);
			}
		}else {
			affiliationMonth= versionDate;
			showMonth = LocalDateTimeUtils.getLastMonth(versionDate);
		}
		
    	//详情页面展示的月份
    	List<String> months = getSupplyConfirmDetailMonths(showMonth);
		
		//获取数据权限
    	long dpStart = System.currentTimeMillis();
    	List<String> projectIds = prepareUserDataPermission();
    	long dpEnd = System.currentTimeMillis();
		log.info("###############获取数据权耗时（毫秒）: "+ (dpEnd-dpStart));
		
		//项目父级
		long fStart = System.currentTimeMillis();
    	List<ProjectByStages> allOrgList = supplyPlanVersionService.selectProjectParentList();
    	long fEnd = System.currentTimeMillis();
		log.info("###############项目父级信息耗时（毫秒）: "+ (fEnd-fStart));
		
		//获取数据
		List<DmDmSupplyConfirmReport> list = dmDmSupplyConfirmReportService.queryList(affiliationMonth,projectIds,projectName,status);
		List<DmDmSupplyConfirmReportMonth> monthList = dmDmSupplyConfirmReportService.queryMonthList(affiliationMonth);
		
		List<String> projectList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyConfirmVO> dataList =  Collections.synchronizedList(new ArrayList<>());
		
		if(CollectionUtils.isNotEmpty(list)) {
			for(DmDmSupplyConfirmReport report : list) {
				SupplyConfirmVO dataVo = new SupplyConfirmVO();
				
				dataVo.setId(report.getProjectfId());
        		dataVo.setCode(report.getProjectfCode());
        		dataVo.setName(report.getProjectfName()+"("+report.getVersionName()+")");
        		dataVo.setPid(report.getProjectId());
        		dataVo.setType(OrgTypeEunm.ORG_STAGE.getKey());
        		//年度
        		SupplyPlanValueDetailDto yearData = new SupplyPlanValueDetailDto();
        		yearData.setParkingNum(report.getPlanStallNum());
        		yearData.setRoomNum(report.getPlanRoomNum());
        		yearData.setArea(report.getPlanArea());
        		yearData.setNotCommodityValue(report.getPlanStallPrice());
        		yearData.setHouseCommodityValue(report.getPlanRoomPrice());
        		yearData.setParkingNumActual(report.getActualStallNum());
        		yearData.setRoomNumActual(report.getActualRoomNum());
        		yearData.setAreaActual(report.getActualArea());
        		yearData.setNotCommodityValueActual(report.getActualStallPrice());
        		yearData.setHouseCommodityValueActual(report.getActualRoomPrice());
        		//月度
        		List<SupplyPlanValueDetailDto> monthDataList = getConfirmMonthData(report.getId(),monthList);
        		
        		dataVo.setYearData(yearData);
        		dataVo.setMonthData(monthDataList);
        		dataList.add(dataVo);
        		projectList.add(report.getProjectId());
			}
		}
		
		//添加项目层级及事业部层级
		long pStart = System.currentTimeMillis();
    	addProjectLevel(projectList,dataList,allOrgList,months);
    	long pEnd = System.currentTimeMillis();
		log.info("###############添加项目层级及事业部层级耗时（毫秒）: "+ (pEnd-pStart));
    	
    	//汇总项目层级数据
		long cpStart = System.currentTimeMillis();
    	collectData(dataList,OrgTypeEunm.ORG_PRODUCTF.getKey());
    	long cpEnd = System.currentTimeMillis();
		log.info("###############汇总项目层级数据耗时（毫秒）: "+ (cpEnd-cpStart));
		
    	//汇总事业部层级数据
		long cdStart = System.currentTimeMillis();
    	collectData(dataList,OrgTypeEunm.ORG_BUSINESS_DIVISION.getKey());
    	long cdEnd = System.currentTimeMillis();
		log.info("###############汇总事业部层级数据耗时（毫秒）: "+ (cdEnd-cdStart));
		
    	//处理均价
		long avgStart = System.currentTimeMillis();
    	for(SupplyConfirmVO vo : dataList) {
    		SupplyPlanValueDetailDto yearData = vo.getYearData();
    		List<SupplyPlanValueDetailDto> monthData = vo.getMonthData();
    		
    		yearData.setHouseAvg(NumberUtils.divide(yearData.getHouseCommodityValue(), yearData.getArea(), 4));
    		yearData.setParkingAvg(NumberUtils.divide(yearData.getNotCommodityValue(),yearData.getParkingNum() == null ? null: new BigDecimal(yearData.getParkingNum()), 4));
    		yearData.setHouseAvgActual(NumberUtils.divide(yearData.getHouseCommodityValueActual(), yearData.getAreaActual(), 4));
    		yearData.setParkingAvgActual(NumberUtils.divide(yearData.getNotCommodityValueActual(),yearData.getParkingNumActual() == null ? null: new BigDecimal(yearData.getParkingNumActual()),4));
    		
    		for(SupplyPlanValueDetailDto monthObj : monthData) {
    			monthObj.setHouseAvg(NumberUtils.divide(monthObj.getHouseCommodityValue(), monthObj.getArea(), 4));
    			monthObj.setParkingAvg(NumberUtils.divide(monthObj.getNotCommodityValue(),monthObj.getParkingNum() == null ? null: new BigDecimal(monthObj.getParkingNum()), 4));
    		}
    	}
    	long avgEnd = System.currentTimeMillis();
		log.info("###############处理均价耗时（毫秒）: "+ (avgEnd-avgStart));
    	
    	//处理页面显示数据
		long showStart = System.currentTimeMillis();
    	for(SupplyConfirmVO dataVo : dataList) {
    		SupplyConfirmDetailVO vo = new SupplyConfirmDetailVO();
    		vo.setId(dataVo.getId());
    		vo.setCode(dataVo.getCode());
    		vo.setName(dataVo.getName());
    		vo.setPid(dataVo.getPid());
    		vo.setType(dataVo.getType());
    		vo.setYear(showMonth.split("-")[0]);
    		if(dataVo.getType().equals(OrgTypeEunm.ORG_PRODUCTF.getKey())) {
    			DmDmSupplyConfirmReport report = getDmDmSupplyConfirmReport(list,dataVo.getId());
    			if(report != null) {
    				vo.setConfirmStatus(report.getConfirmStatus());
    				vo.setConfirmBy(StrUtils.isEmpty(report.getConfirmUserName()) ? report.getPrincipal() : report.getConfirmUserName());
            		if(report.getConfirmTime() != null) {
            			vo.setConfirmTime(LocalDateTimeUtils.formatTime(report.getConfirmTime(),"yyyy-MM-dd HH:mm"));
            		}
    			}
    		}
    		SupplyPlanValueDetailDto yearData = dataVo.getYearData();
    		List<SupplyPlanValueDetailDto> monthData = dataVo.getMonthData();
    		vo.setYearNum(EmptyUtils.handleNumNullValue(yearData.getRoomNum() + "/" + yearData.getParkingNum()));
    		vo.setYearArea(EmptyUtils.handleAreaNullValue(yearData.getArea()));
    		vo.setYearAvgPrice(EmptyUtils.handleAvgNullValue(yearData.getHouseAvg() + "/" + yearData.getParkingAvg()));
    		vo.setYearPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(4, yearData.getHouseCommodityValue(), yearData.getNotCommodityValue()) + "/" + yearData.getHouseCommodityValue() +"/" + yearData.getNotCommodityValue()));
    		vo.setYearActualNum(EmptyUtils.handleNumNullValue(yearData.getRoomNumActual()+"/"+yearData.getParkingNumActual()));
    		vo.setYearActualArea(EmptyUtils.handleAreaNullValue(yearData.getAreaActual()));
    		vo.setYearActualAveragePrice(EmptyUtils.handleAvgNullValue(yearData.getHouseAvgActual()+"/"+yearData.getParkingAvgActual()));
    		vo.setYearActualPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(4, yearData.getHouseCommodityValueActual(), yearData.getNotCommodityValueActual()) + "/" + yearData.getHouseCommodityValueActual() +"/" + yearData.getNotCommodityValueActual()));
    		//达成率=实际货值/计划货值
    		BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,dataVo.getYearData().getHouseCommodityValueActual(),dataVo.getYearData().getNotCommodityValueActual());
    		BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,dataVo.getYearData().getHouseCommodityValue(),dataVo.getYearData().getNotCommodityValue());
    		if(sumPrice  == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
    			vo.setAchievingRate("-");
    		}else {
    			vo.setAchievingRate(NumberUtils.divide(sumPriceActual,sumPrice,4)+"");
    		}
    		//月度
    		List<SupplyConfirmMonthDetailVO> monthDataList = Collections.synchronizedList(new ArrayList<>());
    		for(SupplyPlanValueDetailDto month : monthData) { 
    			SupplyConfirmMonthDetailVO monthVo = new SupplyConfirmMonthDetailVO();
    			monthVo.setMonth(month.getMonth());
    			monthVo.setNum(EmptyUtils.handleNumNullValue(month.getRoomNum() + "/" + month.getParkingNum()));
    			monthVo.setSaleArea(EmptyUtils.handleAreaNullValue(month.getArea()));
    			monthVo.setAvgPrice(EmptyUtils.handleAvgNullValue(month.getHouseAvg() +"/" + month.getParkingAvg()));
    			monthVo.setPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(4, month.getHouseCommodityValue(), month.getNotCommodityValue()) + "/" + month.getHouseCommodityValue() +"/" + month.getNotCommodityValue()));
    			
    			monthDataList.add(monthVo);
    		}
    		vo.setMonthData(monthDataList);
    		
    		resList.add(vo);
    	}
    	long showEnd = System.currentTimeMillis();
		log.info("###############处理页面显示数据耗时（毫秒）: "+ (showEnd-showStart));
		
		return resList;
	}
	
	private DmDmSupplyConfirmReport getDmDmSupplyConfirmReport(List<DmDmSupplyConfirmReport> list,String id) {
		for(DmDmSupplyConfirmReport report : list) {
			if(report.getProjectId().equals(id)) {
				return report;
			}
		}
		return null;
	}

	private List<SupplyPlanValueDetailDto> getConfirmMonthData(String id,
			List<DmDmSupplyConfirmReportMonth> monthList) {
		List<SupplyPlanValueDetailDto> monthDataList = Collections.synchronizedList(new ArrayList<>());
		for(DmDmSupplyConfirmReportMonth report : monthList) {
			if(report.getPkId().equals(id)) {
				SupplyPlanValueDetailDto monthData = new SupplyPlanValueDetailDto();
				monthData.setMonth(report.getShowMonth());
				monthData.setParkingNum(report.getStallNum());
				monthData.setRoomNum(report.getRoomNum());
				monthData.setArea(report.getArea());
				monthData.setNotCommodityValue(report.getStallPrice());
				monthData.setHouseCommodityValue(report.getRoomPrice());
				monthDataList.add(monthData);
			}
		}
		return monthDataList;
	}

	private List<SupplyConfirmDetailVO> prepareGroupSupplyConfirmDetail(String projectName,Integer status,String versionDate) {
		List<SupplyConfirmDetailVO> resList = Collections.synchronizedList(new ArrayList<>());
		String affiliationMonth = "";
		String showMonth = "";
		long dateStart = System.currentTimeMillis();
		if(LocalDateTimeUtils.isSameMonth(versionDate)) {
			if(redisTemplateUtil.get(Constants.RedisConfirmDate) == null) {
				affiliationMonth = supplyPlanVersionService.getAffiliationMonth(versionDate);
			}else {
				affiliationMonth = (String) redisTemplateUtil.get(Constants.RedisConfirmDate);
			}
			if(redisTemplateUtil.get(Constants.RedisConfirmShowDate) == null) {
				showMonth = prepareConfirmShowDate(versionDate, affiliationMonth);
			}else {
				showMonth = (String) redisTemplateUtil.get(Constants.RedisConfirmShowDate);
			}
		}else {
			affiliationMonth= versionDate;
			showMonth = LocalDateTimeUtils.getLastMonth(versionDate);
		}
		long dateEnd = System.currentTimeMillis();
		log.info("###############处理时间耗时（毫秒）: "+ (dateEnd-dateStart));
		
		int year = Integer.parseInt(showMonth.split("-")[0]);
		
		String endConfirmDate = LocalDateTimeUtils.getEndConfirmDate(affiliationMonth);
    	//详情页面展示的月份
    	List<String> months = getSupplyConfirmDetailMonths(showMonth);
    	//获取数据权限
    	long dpStart = System.currentTimeMillis();
    	List<String> projectIds = prepareUserDataPermission();
    	long dpEnd = System.currentTimeMillis();
		log.info("###############获取数据权耗时（毫秒）: "+ (dpEnd-dpStart));
    	
    	//获取事业部或全集团下 项目存在动态版的版本信息
		long vStart = System.currentTimeMillis();
    	List<SupplyPlanVersionDto> supplyPlanVersionList = supplyPlanVersionService.selectDynamicVersionByOrgIdAndDate(projectIds,projectName,status,affiliationMonth,endConfirmDate);
    	long vEnd = System.currentTimeMillis();
    	//所有版本ID
    	List<String> versionIds = supplyPlanVersionList.stream().map(SupplyPlanVersionDto::getId).collect(toList());
		log.info("###############获取供货版本数据耗时（毫秒）: "+ (vEnd-vStart));
		
    	//所有版本详情
		long vdStart = System.currentTimeMillis();
    	List<SupplyPlanVersionDetail> versionDataList = supplyPlanVersionService.selectVersionDetailList(versionIds);
    	long vdEnd = System.currentTimeMillis();
		log.info("###############获取供货版本详情数据耗时（毫秒）: "+ (vdEnd-vdStart));
		
    	//去除不需要确认供货的项目信息
		long hStart = System.currentTimeMillis();
    	List<SupplyPlanVersionDto> resSupplyPlanVersionList = prepareVersionList(supplyPlanVersionList,versionDataList);
    	long hEnd = System.currentTimeMillis();
		log.info("###############去除不需要确认供货的项目信息耗时（毫秒）: "+ (hEnd-hStart));
		
    	//项目父级
		long fStart = System.currentTimeMillis();
    	List<ProjectByStages> allOrgList = supplyPlanVersionService.selectProjectParentList();
    	long fEnd = System.currentTimeMillis();
		log.info("###############项目父级信息耗时（毫秒）: "+ (fEnd-fStart));
    	
		long cStart = System.currentTimeMillis();
    	List<SupplyConfirmRecord> confirmRecordList =  supplyConfirmRecordService.selectConfirmRecordList(affiliationMonth);
    	long cEnd = System.currentTimeMillis();
		log.info("###############项目确认信息耗时（毫秒）: "+ (cEnd-cStart));
    	
		long pmStart = System.currentTimeMillis();
    	Map<String, Object> projectPmMap = handleProjectPm(projectIds);
    	long pmEnd = System.currentTimeMillis();
		log.info("###############项目PM（毫秒）: "+ (pmEnd-pmStart));
		
		long dataStart = System.currentTimeMillis();
    	//分期层级数据处理
    	List<SupplyConfirmVO> dataList =  Collections.synchronizedList(new ArrayList<>());
    	List<String> projectList = Collections.synchronizedList(new ArrayList<>());
    	long stageStart = System.currentTimeMillis();
    	if(CollectionUtils.isNotEmpty(resSupplyPlanVersionList)) {
    		for(SupplyPlanVersionDto supplyPlanVersion : resSupplyPlanVersionList) {
    			SupplyConfirmVO dataVo = new SupplyConfirmVO();
    			String versionId = supplyPlanVersion.getId();
        		String projectId = supplyPlanVersion.getProjectId();
        		String versionName = prepareVersionName(supplyPlanVersion);
        		//年度
        		SupplyPlanValueDetailDto yearData = supplyConfirmRecordDetailService.prepareAllYearData(versionId,year,versionDataList);
        		//月度
        		List<SupplyPlanValueDetailDto> monthDataList = Collections.synchronizedList(new ArrayList<>());
        		for(String month : months) {
        			SupplyPlanValueDetailDto monthData = supplyConfirmRecordDetailService.prepareAllMonthData(versionId,month,versionDataList);
        			monthData.setMonth(month);
        			monthDataList.add(monthData);
        		}
        		
        		dataVo.setId(supplyPlanVersion.getProjectfId());
        		dataVo.setCode(supplyPlanVersion.getStageCode());
        		dataVo.setName(supplyPlanVersion.getStageName()+"("+versionName+")");
        		dataVo.setPid(projectId);
        		dataVo.setType(OrgTypeEunm.ORG_STAGE.getKey());
        		dataVo.setYearData(yearData);
        		dataVo.setMonthData(monthDataList);
        		dataList.add(dataVo);
        		projectList.add(projectId);
        	}
    	}
    	long stageEnd = System.currentTimeMillis();
		log.info("###############处理分期及以下数据耗时（毫秒）: "+ (stageEnd-stageStart));
    	
    	//添加项目层级及事业部层级
		long pStart = System.currentTimeMillis();
    	addProjectLevel(projectList,dataList,allOrgList,months);
    	long pEnd = System.currentTimeMillis();
		log.info("###############添加项目层级及事业部层级耗时（毫秒）: "+ (pEnd-pStart));
    	
    	//汇总项目层级数据
		long cpStart = System.currentTimeMillis();
    	collectData(dataList,OrgTypeEunm.ORG_PRODUCTF.getKey());
    	long cpEnd = System.currentTimeMillis();
		log.info("###############汇总项目层级数据耗时（毫秒）: "+ (cpEnd-cpStart));
		
    	//汇总事业部层级数据
		long cdStart = System.currentTimeMillis();
    	collectData(dataList,OrgTypeEunm.ORG_BUSINESS_DIVISION.getKey());
    	long cdEnd = System.currentTimeMillis();
		log.info("###############汇总事业部层级数据耗时（毫秒）: "+ (cdEnd-cdStart));
		
		
    	//处理均价
		long avgStart = System.currentTimeMillis();
    	for(SupplyConfirmVO vo : dataList) {
    		SupplyPlanValueDetailDto yearData = vo.getYearData();
    		List<SupplyPlanValueDetailDto> monthData = vo.getMonthData();
    		
    		yearData.setHouseAvg(NumberUtils.divide(yearData.getHouseCommodityValue(), yearData.getArea(), 4));
    		yearData.setParkingAvg(NumberUtils.divide(yearData.getNotCommodityValue(),yearData.getParkingNum() == null ? null: new BigDecimal(yearData.getParkingNum()), 4));
    		yearData.setHouseAvgActual(NumberUtils.divide(yearData.getHouseCommodityValueActual(), yearData.getAreaActual(), 4));
    		yearData.setParkingAvgActual(NumberUtils.divide(yearData.getNotCommodityValueActual(),yearData.getParkingNumActual() == null ? null: new BigDecimal(yearData.getParkingNumActual()),4));
    		
    		for(SupplyPlanValueDetailDto monthObj : monthData) {
    			monthObj.setHouseAvg(NumberUtils.divide(monthObj.getHouseCommodityValue(), monthObj.getArea(), 4));
    			monthObj.setParkingAvg(NumberUtils.divide(monthObj.getNotCommodityValue(),monthObj.getParkingNum() == null ? null: new BigDecimal(monthObj.getParkingNum()), 4));
    		}
    	}
    	long avgEnd = System.currentTimeMillis();
		log.info("###############处理均价耗时（毫秒）: "+ (avgEnd-avgStart));
    	
    	
    	//处理页面显示数据
		long showStart = System.currentTimeMillis();
    	for(SupplyConfirmVO dataVo : dataList) {
    		SupplyConfirmDetailVO vo = new SupplyConfirmDetailVO();
    		vo.setId(dataVo.getId());
    		vo.setCode(dataVo.getCode());
    		vo.setName(dataVo.getName());
    		vo.setPid(dataVo.getPid());
    		vo.setType(dataVo.getType());
    		
    		if(dataVo.getType().equals(OrgTypeEunm.ORG_PRODUCTF.getKey())) {
    			SupplyConfirmRecord record = getSupplyConfirmRecord(dataVo.getId(),confirmRecordList);
    			if(record != null) {
    				if(record.getConfirmStatus() != null && record.getConfirmStatus().intValue() == 1) {
    					vo.setConfirmStatus(record.getConfirmStatus());
        			}else {
        				vo.setConfirmStatus(0);
        			}
        			if(StrUtils.isNotEmpty(record.getConfirmUserName())) {
        				vo.setConfirmBy(record.getConfirmUserName());
        			}else {
        				vo.setConfirmBy(record.getPrincipal());
        			}
        			if(record.getConfirmTime() != null) {
        				vo.setConfirmTime(LocalDateTimeUtils.formatTime(record.getConfirmTime(),"yyyy-MM-dd HH:mm"));
        			}	
    			}else {
    				if(projectPmMap != null && !projectPmMap.isEmpty()) {
    					vo.setConfirmBy(String.valueOf(projectPmMap.get(dataVo.getId())));
    				}
    			}
    		}
    		SupplyPlanValueDetailDto yearData = dataVo.getYearData();
    		List<SupplyPlanValueDetailDto> monthData = dataVo.getMonthData();
    		vo.setYearNum(EmptyUtils.handleNumNullValue(yearData.getRoomNum() + "/" + yearData.getParkingNum()));
    		vo.setYearArea(EmptyUtils.handleAreaNullValue(yearData.getArea()));
    		vo.setYearAvgPrice(EmptyUtils.handleAvgNullValue(yearData.getHouseAvg() + "/" + yearData.getParkingAvg()));
    		vo.setYearPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(4, yearData.getHouseCommodityValue(), yearData.getNotCommodityValue()) + "/" + yearData.getHouseCommodityValue() +"/" + yearData.getNotCommodityValue()));
    		vo.setYearActualNum(EmptyUtils.handleNumNullValue(yearData.getRoomNumActual()+"/"+yearData.getParkingNumActual()));
    		vo.setYearActualArea(EmptyUtils.handleAreaNullValue(yearData.getAreaActual()));
    		vo.setYearActualAveragePrice(EmptyUtils.handleAvgNullValue(yearData.getHouseAvgActual()+"/"+yearData.getParkingAvgActual()));
    		vo.setYearActualPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(4, yearData.getHouseCommodityValueActual(), yearData.getNotCommodityValueActual()) + "/" + yearData.getHouseCommodityValueActual() +"/" + yearData.getNotCommodityValueActual()));
    		//达成率=实际货值/计划货值
    		BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,dataVo.getYearData().getHouseCommodityValueActual(),dataVo.getYearData().getNotCommodityValueActual());
    		BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,dataVo.getYearData().getHouseCommodityValue(),dataVo.getYearData().getNotCommodityValue());
    		if(sumPrice  == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
    			vo.setAchievingRate("-");
    		}else {
    			vo.setAchievingRate(NumberUtils.divide(sumPriceActual,sumPrice,4)+"");
    		}
    		//月度
    		List<SupplyConfirmMonthDetailVO> monthDataList = Collections.synchronizedList(new ArrayList<>());
    		for(SupplyPlanValueDetailDto month : monthData) { 
    			SupplyConfirmMonthDetailVO monthVo = new SupplyConfirmMonthDetailVO();
    			monthVo.setMonth(month.getMonth());
    			monthVo.setNum(EmptyUtils.handleNumNullValue(month.getRoomNum() + "/" + month.getParkingNum()));
    			monthVo.setSaleArea(EmptyUtils.handleAreaNullValue(month.getArea()));
    			monthVo.setAvgPrice(EmptyUtils.handleAvgNullValue(month.getHouseAvg() +"/" + month.getParkingAvg()));
    			monthVo.setPrice(EmptyUtils.handlePriceNullValue(NumberUtils.BigDecimalADD(4, month.getHouseCommodityValue(), month.getNotCommodityValue()) + "/" + month.getHouseCommodityValue() +"/" + month.getNotCommodityValue()));
    			
    			monthDataList.add(monthVo);
    		}
    		vo.setMonthData(monthDataList);
    		
    		resList.add(vo);
    	}
    	long showEnd = System.currentTimeMillis();
		log.info("###############处理页面显示数据耗时（毫秒）: "+ (showEnd-showStart));
    	
    	
    	long dataEnd = System.currentTimeMillis();
		log.info("###############处理数据总耗时（毫秒）: "+ (dataEnd-dataStart));
    	
		return resList;
	}

	private List<String> prepareUserDataPermission() {
        Set<String> projectIds = new TreeSet<>();
        String userName = getOperator().getUsername();
        List<ProjectByStagesDto> dataPermissionList = idmUserService.queryUserDataPermissions(userName);
        if (CollectionUtils.isNotEmpty(dataPermissionList)) {
        	 for (ProjectByStagesDto dto : dataPermissionList) {
                 if (dto.getHrOrgTypeId().equals(HrOrgTypeEunm.ORG_31.getKey())) {
                     projectIds.add(dto.getOrgdepid());
                 }
             }
        } 
        return new ArrayList<>(projectIds);
    }
	
	private List<SupplyPlanVersionDto> prepareVersionList(List<SupplyPlanVersionDto> supplyPlanVersionList,List<SupplyPlanVersionDetail> versionDataList) {
		List<SupplyPlanVersionDto> resList = Collections.synchronizedList(new LinkedList<>());
		Set<String> projectList = new TreeSet<String>();
		for(SupplyPlanVersionDto version : supplyPlanVersionList) {
			boolean flag = isAllSupply(version.getId(),versionDataList);
			if(!flag) {
				projectList.add(version.getProjectId());
			}
		}
		if(CollectionUtils.isNotEmpty(projectList)) {
			for(String projectId : projectList) {
				for(SupplyPlanVersionDto version : supplyPlanVersionList) {
					if(projectId.equals(version.getProjectId())) {
						resList.add(version);
					}
				}
				
			}
		}
		return resList;
	}
	
	private boolean isAllSupply(String versionId,List<SupplyPlanVersionDetail> versionDataList) {
		for(SupplyPlanVersionDetail detail : versionDataList) {
			if(detail.getVersionId().equals(versionId)) {
				if(detail.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
					Integer isSupply = detail.getIsSupply();
					String bussinessType = detail.getBusinessType();
					if(bussinessType.equals(SalyTypeEnum.SALABLE.getKey()) || bussinessType.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()) ) {
						if(isSupply != null && isSupply.intValue() == 0) {
							return false;
						}
					}
				}
			}
		}
		return true;
	}
	
	private SupplyConfirmRecord getSupplyConfirmRecord(String projectId, List<SupplyConfirmRecord> confirmRecordList) {
		if(CollectionUtils.isNotEmpty(confirmRecordList)) {
			for(SupplyConfirmRecord obj : confirmRecordList) {
				if(obj.getProjectId().equals(projectId)) {
					return obj;
				}
			}
		}
		return null;
	}
	
	private Map<String, Object> handleProjectPm(List<String> projectIds) {
		Map<String, Object> projectPmMap;
		if(redisTemplateUtil.get(Constants.PROJECT_PM_USER) != null) {
    		projectPmMap = (Map<String, Object>) redisTemplateUtil.get(Constants.PROJECT_PM_USER);
    	}else {
    		projectPmMap = prepareProjectPm(projectIds);
    	}
		return projectPmMap;
	}
	
	private Map<String, Object> prepareProjectPm(List<String> projectIds) {
		Map<String, Object> map = new HashMap<String, Object>();
		for(String projectId : projectIds) {
			String user = getProjectPmUser(projectId);
			map.put(projectId, user);
		}
		return map;
	}

	private String getProjectPmUser(String projectId) {
		StringBuilder sb = new StringBuilder();
		String squ = "";
		HashSet<GroupUserVo> set = idmUserService.getGroupUserInfo(Constants.PROJECT_OPERATION_PM,projectId);
		for(GroupUserVo vo : set) {
			sb.append(squ).append(vo.getUsercn());
			squ ="、";
		}
		return sb.toString();
	}
	
	private void collectData(List<SupplyConfirmVO> dataList, String type) {
		for(SupplyConfirmVO vo : dataList) {
			if(vo.getType().equals(type)) {
				List<SupplyConfirmVO> childList = getAllChildList(vo.getId(),dataList);
				collectChildData(vo,childList);
			}
		}
		
	}

	private void collectChildData(SupplyConfirmVO vo, List<SupplyConfirmVO> childList) {
		SupplyPlanValueDetailDto parentYearData = vo.getYearData();
		List<SupplyPlanValueDetailDto> parentMonthData = vo.getMonthData();
		if(CollectionUtils.isNotEmpty(childList)) {
			for(SupplyConfirmVO obj : childList) {
				SupplyPlanValueDetailDto yearData = obj.getYearData();
				List<SupplyPlanValueDetailDto> monthData = obj.getMonthData();
				
				parentYearData.setRoomNum(NumberUtils.intADD(parentYearData.getRoomNum(),yearData.getRoomNum()));
				parentYearData.setParkingNum(NumberUtils.intADD(parentYearData.getParkingNum(), yearData.getParkingNum()));
				parentYearData.setArea(NumberUtils.BigDecimalADD(4, parentYearData.getArea(), yearData.getArea()));
				parentYearData.setHouseCommodityValue(NumberUtils.BigDecimalADD(4, parentYearData.getHouseCommodityValue(), yearData.getHouseCommodityValue()));
				parentYearData.setNotCommodityValue(NumberUtils.BigDecimalADD(4, parentYearData.getNotCommodityValue(), yearData.getNotCommodityValue()));
				
				parentYearData.setRoomNumActual(NumberUtils.intADD(parentYearData.getRoomNumActual(),yearData.getRoomNumActual()));
				parentYearData.setParkingNumActual(NumberUtils.intADD(parentYearData.getParkingNumActual(), yearData.getParkingNumActual()));
				parentYearData.setAreaActual(NumberUtils.BigDecimalADD(4, parentYearData.getAreaActual(), yearData.getAreaActual()));
				parentYearData.setHouseCommodityValueActual(NumberUtils.BigDecimalADD(4, parentYearData.getHouseCommodityValueActual(), yearData.getHouseCommodityValueActual()));
				parentYearData.setNotCommodityValueActual(NumberUtils.BigDecimalADD(4, parentYearData.getNotCommodityValueActual(), yearData.getNotCommodityValueActual()));
			
				for(SupplyPlanValueDetailDto parentMonthObj : parentMonthData) {
					for(SupplyPlanValueDetailDto monthObj : monthData) {
						if(parentMonthObj.getMonth().equals(monthObj.getMonth())) {
							parentMonthObj.setRoomNum(NumberUtils.intADD(parentMonthObj.getRoomNum(),monthObj.getRoomNum()));
							parentMonthObj.setParkingNum(NumberUtils.intADD(parentMonthObj.getParkingNum(), monthObj.getParkingNum()));
							parentMonthObj.setArea(NumberUtils.BigDecimalADD(4, parentMonthObj.getArea(), monthObj.getArea()));
							parentMonthObj.setHouseCommodityValue(NumberUtils.BigDecimalADD(4, parentMonthObj.getHouseCommodityValue(), monthObj.getHouseCommodityValue()));
							parentMonthObj.setNotCommodityValue(NumberUtils.BigDecimalADD(4, parentMonthObj.getNotCommodityValue(), monthObj.getNotCommodityValue()));
						}
					}
				}
			}
		}
		
	}

	private List<SupplyConfirmVO> getAllChildList(String id, List<SupplyConfirmVO> dataList) {
		List<SupplyConfirmVO> list = Collections.synchronizedList(new ArrayList<>());
		if(CollectionUtils.isNotEmpty(dataList)) {
			for(SupplyConfirmVO vo : dataList) {
				if(vo.getPid().equals(id)) {
					list.add(vo);
				}
			}
		}
		return list;
	}

	private void addProjectLevel(List<String> projectList, List<SupplyConfirmVO> dataList,
			List<ProjectByStages> allOrgList,List<String> months) {
		List<SupplyConfirmVO> resList = Collections.synchronizedList(new ArrayList<>());
		if(CollectionUtils.isNotEmpty(projectList)) {
			for(String projectId : projectList) {
				SupplyConfirmVO projectVo = new SupplyConfirmVO();
				//项目层级
				ProjectByStages projectObj = getOrgData(projectId,allOrgList);
				if(projectObj != null) {
					//事业部层级
					ProjectByStages companyObj = getOrgData(projectObj.getParentOrgid(),allOrgList);
					if(companyObj != null) {
						ProjectByStages businessDivisionObj = getOrgData(companyObj.getParentOrgid(),allOrgList);
						if(businessDivisionObj != null) {
							projectVo.setId(projectId);
							projectVo.setName(projectObj.getOrgname());
							projectVo.setPid(businessDivisionObj.getOrgdepid());
							projectVo.setType(OrgTypeEunm.ORG_PRODUCTF.getKey());
							projectVo.setYearData(new SupplyPlanValueDetailDto());
							List<SupplyPlanValueDetailDto> pMonthDataList = initConfirmMonthData(months);
							projectVo.setMonthData(pMonthDataList);
							resList.add(projectVo);
						
							//事业部层级
							SupplyConfirmVO businessDivisionVo = new SupplyConfirmVO();
							businessDivisionVo.setId(businessDivisionObj.getOrgdepid());
							businessDivisionVo.setName(businessDivisionObj.getOrgname());
							businessDivisionVo.setPid(Constants.ROOT_NODE_PID);
							businessDivisionVo.setType(OrgTypeEunm.ORG_BUSINESS_DIVISION.getKey());
							businessDivisionVo.setYearData(new SupplyPlanValueDetailDto());
							List<SupplyPlanValueDetailDto> dMonthDataList = initConfirmMonthData(months);
							businessDivisionVo.setMonthData(dMonthDataList);
							resList.add(businessDivisionVo);
						}
					}
				}
			}
			
			//去重
			List<SupplyConfirmVO> lastList = resList.stream().collect(
	                Collectors.collectingAndThen(
	                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SupplyConfirmVO::getId))), ArrayList::new)
	        );
			
			dataList.addAll(lastList);
		}
	}
	
	private List<SupplyPlanValueDetailDto> initConfirmMonthData(List<String> months) {
		//月度
		List<SupplyPlanValueDetailDto> monthDataList = Collections.synchronizedList(new ArrayList<>());
		for(String month : months) {
			SupplyPlanValueDetailDto dto = new SupplyPlanValueDetailDto();
			dto.setMonth(month);
			monthDataList.add(dto);
		}
		return monthDataList;
	}

	private ProjectByStages getOrgData(String projectId,List<ProjectByStages> allOrgList) {
		if(CollectionUtils.isNotEmpty(allOrgList)) {
			for(ProjectByStages obj : allOrgList) {
				if(obj.getOrgdepid().equals(projectId)) {
					return obj;
				}
			}
		}
		return null;
	}

	private List<String> getSupplyConfirmDetailMonths(String showMonth) {
		int year = Integer.parseInt(showMonth.split("-")[0]);
		int month = Integer.parseInt(showMonth.split("-")[1]);
		List<String> months = Collections.synchronizedList(new ArrayList<>());
		if (month == Constants.TWELVE) {
			year = year + 1;
			for (int i = 1; i <= Constants.TWELVE; i++) {
				if (i < 10) {
					months.add(year + "-" + "0" + i);
				} else {
					months.add(year + "-" + i);
				}
			}
		} else {
			for (int i = month + 1; i <= Constants.TWELVE; i++) {
				if (i < 10) {
					months.add(year + "-" + "0" + i);
				} else {
					months.add(year + "-" + i);
				}
			}
		}
		return months;
	}

	private String prepareConfirmShowDate(String versionDate, String affiliationMonth) {
		String showMonth = "";
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
		LocalDateTime now = LocalDateTime.now();
		String comfirmTime = supplyPlanVersionService.getComfirmTime();
		LocalDateTime endComfirmTime = LocalDateTimeUtils.strToDate(comfirmTime, df);
		LocalDateTime beginTimeTemp = endComfirmTime.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
		LocalDateTime beginComfirmTime = beginTimeTemp.with(TemporalAdjusters.lastDayOfMonth()).minusDays(1);
		if(now.isBefore(beginComfirmTime)) {
			showMonth = LocalDateTimeUtils.getLastMonth(versionDate);
		}else {
			showMonth = affiliationMonth;
		}
		return showMonth;
	}

	@Override
	public R supplyConfirm(String apiVersion, String projectId,String versionDate) {
		IdmUser user = getOperator();
		String projectPrincipal = getProjectPmUser(projectId);
		supplyConfirmRecordService.confirmSupply(projectId,versionDate,user,projectPrincipal);
		saveLog("供货计划","保存供货确认","项目ID："+projectId+";处理人："+projectPrincipal);
		return ok();
	}
	
	@Override
	public R cancelSupplyConfirm(String apiVersion, String projectId,String versionDate) {
		String alias = getOperator().getAlias();
		supplyConfirmRecordService.cancelSupplyConfirm(projectId,versionDate,alias);
		saveLog("供货计划","取消供货确认","项目ID："+projectId+"；处理人："+alias);
		return ok();
	}
	
	@Override
	public void overAllValueExport(String apiVersion,HttpServletRequest request,HttpServletResponse response,String projectId,String code) {
		List<SupplyPlanExcelVO> resList = Collections.synchronizedList(new LinkedList<>());
		//获取项目信息
    	MdmProject project = projectService.selectByProjectId(projectId,IsDeleteEnum.NO.getKey());
    	Set<String> yearSet = getYears(projectId);
		prepareProjectData(resList,project,yearSet);
		ProjectExcelValueVO projectData = initProject(yearSet);
		String projectName = project.getProjectName();
		List<SupplyPlanVersion> supplyPlanVersionList =getNewestVersion(projectId,"");
		if(CollectionUtils.isNotEmpty(supplyPlanVersionList)) {
			for(SupplyPlanVersion version : supplyPlanVersionList) {
				List<SupplyPlanExcelVO> collect = Collections.synchronizedList(new ArrayList<>());
				String versionId = version.getId();
				String versionType = version.getVersionType();
				String versionAttr = version.getVersionAttr();
				if(StrUtils.isNotEmpty(versionAttr) && versionAttr.equals(VersionAttrEnum.BEFORE_WARPLAN.getKey())) {
					versionType = VersionTypeEunm.INVESTMENT.getKey();
				}
				String stageId = version.getProjectfId();
				String createTime = LocalDateTimeUtils.formatTime(version.getCreateTime(),DateUtils.DATE_JFP_STR);
				List<Map<String, Object>> stagePart = supplyPlanVersionService.selectStageInfo(stageId,createTime);
				StagePartNers stagePartNers = stagePartNersService.getStagePartnersByProjectFid(version.getProjectfId());

				//拼装搜索条件
				String condition = StrUtils.prepareOverCondition(code,versionType);
				//全盘供货计划与实际
				List<SupplyPlanVersionDetail> alllist = supplyPlanExportService.collectSupplyPlanVersionDetailList(versionType,versionId);
				List<SupplyYearValueVO> yearValue  = Collections.synchronizedList(new ArrayList<>());
				for(String year : yearSet) {
					SupplyYearValueVO vo = new SupplyYearValueVO();
					vo.setYear(year);
					//年度合计
					List<SupplyPlanVersionDetail> yearList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,"");
					vo.setYearList(yearList);
					//年度月份合计
					List<SupplyPlanVersionDetail> oneList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.january.getValue());
					vo.setOneList(oneList);
					List<SupplyPlanVersionDetail> twoList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.february.getValue());
					vo.setTwoList(twoList);
					List<SupplyPlanVersionDetail> threeList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.march.getValue());
					vo.setThreeList(threeList);
					List<SupplyPlanVersionDetail> fourList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.april.getValue());
					vo.setFourList(fourList);
					List<SupplyPlanVersionDetail> fiveList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.may.getValue());
					vo.setFiveList(fiveList);
					List<SupplyPlanVersionDetail> sixList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.june.getValue());
					vo.setSixList(sixList);
					List<SupplyPlanVersionDetail> sevenList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.july.getValue());
					vo.setSevenList(sevenList);
					List<SupplyPlanVersionDetail> eigthList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.august.getValue());
					vo.setEigthList(eigthList);
					List<SupplyPlanVersionDetail> nineList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.september.getValue());
					vo.setNineList(nineList);
					List<SupplyPlanVersionDetail> tenList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.october.getValue());
					vo.setTenList(tenList);
					List<SupplyPlanVersionDetail> elevenList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.november.getValue());
					vo.setElevenList(elevenList);
					List<SupplyPlanVersionDetail> twelevList = supplyPlanExportService.collectDetailList(alllist,versionType,condition,year,MonthEnum.december.getValue());
					vo.setTwelevList(twelevList);
					yearValue.add(vo);
				}
				
				if(CollectionUtils.isNotEmpty(alllist)) {
					for(SupplyPlanVersionDetail all : alllist) {
						SupplyPlanExcelVO vo = new SupplyPlanExcelVO();
						vo.setId(all.getId());
						vo.setName(all.getOrgName());
						vo.setPid(all.getPid());
						vo.setType(all.getType());
						vo.setIsParking(all.getIsParking());
						vo.setVersionType(versionType);
						List<YearExcelValueVO> yearExcelValueList = Collections.synchronizedList(new ArrayList<>());
						for(SupplyYearValueVO yearObj : yearValue) {
							YearExcelValueVO yearExcelValue = new YearExcelValueVO();
							String year = yearObj.getYear();
							//年度合计
							List<SupplyPlanVersionDetail> yearList = yearObj.getYearList();
							//年度月份合计
							List<SupplyPlanVersionDetail> oneList = yearObj.getOneList();
						    List<SupplyPlanVersionDetail> twoList = yearObj.getTwoList();
							List<SupplyPlanVersionDetail> threeList = yearObj.getThreeList();
							List<SupplyPlanVersionDetail> fourList = yearObj.getFourList();
							List<SupplyPlanVersionDetail> fiveList =yearObj.getFiveList();
							List<SupplyPlanVersionDetail> sixList = yearObj.getSixList();
							List<SupplyPlanVersionDetail> sevenList = yearObj.getSevenList();
							List<SupplyPlanVersionDetail> eigthList = yearObj.getEigthList();
							List<SupplyPlanVersionDetail> nineList = yearObj.getNineList();
							List<SupplyPlanVersionDetail> tenList = yearObj.getTenList();
							List<SupplyPlanVersionDetail> elevenList = yearObj.getElevenList();
							List<SupplyPlanVersionDetail> twelevList = yearObj.getTwelevList();
							
							BaseExcelValueVO yearValueVO = new BaseExcelValueVO();
							for(SupplyPlanVersionDetail yearVal : yearList) {
								if(all.getId().equals(yearVal.getId())) {
								  yearValueVO = setYearValue(yearVal,projectData,year);
								}
							}
							yearExcelValue.setYear(year);
							yearExcelValue.setYearValueVO(yearValueVO);
							
							List<MonthExcelValueVO> monthValue = getMonthExcelValue(year);
							for(MonthExcelValueVO monthValueVO : monthValue) {
								int monthTemp = Integer.parseInt(monthValueVO.getMonth().split("-")[1]);
								switch (monthTemp) {
								case 1:
									setMonthExcelData(oneList,monthValueVO,all.getId(),projectData,year);
									break;
								case 2:
									setMonthExcelData(twoList,monthValueVO,all.getId(),projectData,year);
									break;
								case 3:
									setMonthExcelData(threeList,monthValueVO,all.getId(),projectData,year);
									break;
								case 4:
									setMonthExcelData(fourList,monthValueVO,all.getId(),projectData,year);
									break;
								case 5:
									setMonthExcelData(fiveList,monthValueVO,all.getId(),projectData,year);
									break;
								case 6:
									setMonthExcelData(sixList,monthValueVO,all.getId(),projectData,year);
									break;
								case 7:
									setMonthExcelData(sevenList,monthValueVO,all.getId(),projectData,year);
									break;
								case 8:
									setMonthExcelData(eigthList,monthValueVO,all.getId(),projectData,year);
									break;
								case 9:
									setMonthExcelData(nineList,monthValueVO,all.getId(),projectData,year);
									break;
								case 10:
									setMonthExcelData(tenList,monthValueVO,all.getId(),projectData,year);
									break;
								case 11:
									setMonthExcelData(elevenList,monthValueVO,all.getId(),projectData,year);
									break;
								case 12:
									setMonthExcelData(twelevList,monthValueVO,all.getId(),projectData,year);
									break;
								default:
									break;
								}
							}
							yearExcelValue.setMonthValueVO(monthValue);
							
							yearExcelValueList.add(yearExcelValue);
						}
						if(vo.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())) {
							vo.setProjectName(project.getProjectName());
							vo.setProjectCode(project.getProjectCode());
							//分期、组团、产品信息
							prepareBuildParentInfo(alllist,all.getPid(),vo,stagePart,stagePartNers);
							vo.setBulidNo(all.getOrgName());
							vo.setPendingHomeSale2(getBuildPendingHomeSale(all.getOrgId(),stagePart));
							vo.setBusinessTypeName(all.getBusinessTypeName());
							vo.setFreeTypeName(all.getFreeTypeName());
							vo.setProTypeName(all.getProTypeName());
							//全盘供货计划与实际
							BaseExcelValueVO overAllValueVO = setOverAllValue(all,projectData);
							vo.setOverAllValueVO(overAllValueVO);
							vo.setYearExcelValueVO(yearExcelValueList);
							collect.add(vo);
						}else if(vo.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
							vo.setProjectName(project.getProjectName());
							vo.setProjectCode(project.getProjectCode());
							//分期、组团信息
							prepareProductParentInfo(alllist,all.getPid(),vo,stagePart,stagePartNers);
							//产品信息
							vo.setProductTypeName(all.getProProductType());
							vo.setProductTypeCode(all.getProProductCode());
							vo.setProductName(all.getOrgName());
							vo.setProductCode(all.getOrgCode());
							if("139".equals(all.getProProductCode())) {
								vo.setIsParking(SupplyEnum.YES.getKey());
							}
							//全盘供货计划与实际
							BaseExcelValueVO overAllValueVO = setOverAllValue(all,projectData);
							vo.setOverAllValueVO(overAllValueVO);
							vo.setYearExcelValueVO(yearExcelValueList);
							collect.add(vo);
						}else if(vo.getType().equals(OrgTypeEunm.ORG_GROUP.getKey())) {
							vo.setProjectName(project.getProjectName());
							vo.setProjectCode(project.getProjectCode());
							//分期信息
							prepareGroupParentInfo(alllist,all.getPid(),vo,stagePart,stagePartNers);
							vo.setGroupName(all.getOrgName());
							//全盘供货计划与实际
							BaseExcelValueVO overAllValueVO = setOverAllValue(all,projectData);
							vo.setOverAllValueVO(overAllValueVO);
							vo.setYearExcelValueVO(yearExcelValueList);
							collect.add(vo);
						}else if(vo.getType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
							vo.setPid(projectId);
							vo.setProjectName(project.getProjectName());
							vo.setProjectCode(project.getProjectCode());
							vo.setStageName(all.getOrgName());
							vo.setStageCode(all.getOrgCode());
							if(CollectionUtils.isNotEmpty(stagePart)) {
								prepareStageData(vo, stagePart, stagePartNers);
							}
							//全盘供货计划与实际
							BaseExcelValueVO overAllValueVO = setOverAllValue(all,projectData);
							vo.setOverAllValueVO(overAllValueVO);
							vo.setYearExcelValueVO(yearExcelValueList);
							collect.add(vo);
						}
					}
				}
				resList.addAll(collect);
			}
		}
		
		//处理项目数据
		for(SupplyPlanExcelVO vo : resList) {
			if(vo.getType().equals(OrgTypeEunm.ORG_PRODUCTF.getKey())) {
				BaseExcelValueVO overAllValueVO = vo.getOverAllValueVO();
				List<YearExcelValueVO> yearValueList = vo.getYearExcelValueVO();
				
				ProjectBaseExcelValueVO proOverAllValue =  projectData.getOverAllValueVO();
				if(proOverAllValue != null) {
					overAllValueVO.setNum(EmptyUtils.handleNum(proOverAllValue.getRoomNum(),proOverAllValue.getParkingNum()));
					overAllValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(proOverAllValue.getSaleArea()));
					overAllValueVO.setAvgPrice(EmptyUtils.handleAvg(proOverAllValue.getHouseCommodityValue(),proOverAllValue.getSaleArea(),proOverAllValue.getNotCommodityValue(),proOverAllValue.getParkingNum()));
					overAllValueVO.setPrice(EmptyUtils.handlePrice(proOverAllValue.getHouseCommodityValue(),proOverAllValue.getNotCommodityValue()));
					overAllValueVO.setActualNum(EmptyUtils.handleNum(proOverAllValue.getRoomNumActual(),proOverAllValue.getParkingNumActual()));
					overAllValueVO.setActualArea(EmptyUtils.handleAreaNullValue(proOverAllValue.getAreaActual()));
					overAllValueVO.setActualAveragePrice(EmptyUtils.handleAvg(proOverAllValue.getHouseCommodityValueActual(),proOverAllValue.getAreaActual(),proOverAllValue.getNotCommodityValueActual(),proOverAllValue.getParkingNumActual()));
					overAllValueVO.setActualPrice(EmptyUtils.handlePrice(proOverAllValue.getHouseCommodityValueActual(),proOverAllValue.getNotCommodityValueActual()));
					
					//达成率=实际货值/计划货值
					BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,proOverAllValue.getHouseCommodityValueActual(),proOverAllValue.getNotCommodityValueActual());
					BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,proOverAllValue.getHouseCommodityValue(),proOverAllValue.getNotCommodityValue());
					if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
						overAllValueVO.setAchievingRate("-");
					}else {
						overAllValueVO.setAchievingRate(StrUtils.divide(sumPriceActual+"",sumPrice+"",4));
					}
					vo.setOverAllValueVO(overAllValueVO);
				}
				
				List<ProjectYearExcelValueVO> projectValueList = projectData.getYearExcelValueVO();
				if(CollectionUtils.isNotEmpty(yearValueList)) {
					for(YearExcelValueVO yearExcelValue : yearValueList) {
						//月份
						List<MonthExcelValueVO> monthValueVO = yearExcelValue.getMonthValueVO();
						//年度
						BaseExcelValueVO yearValueVO = yearExcelValue.getYearValueVO();
						
						if(CollectionUtils.isNotEmpty(projectValueList)) {
							for(ProjectYearExcelValueVO projectValue : projectValueList) {
								if(yearExcelValue.getYear().equals(projectValue.getYear())) {
									yearValueVO.setNum(EmptyUtils.handleNum(projectValue.getYearValueVO().getRoomNum(),projectValue.getYearValueVO().getParkingNum()));
									yearValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(projectValue.getYearValueVO().getSaleArea()));
									yearValueVO.setAvgPrice(EmptyUtils.handleAvg(projectValue.getYearValueVO().getHouseCommodityValue(),projectValue.getYearValueVO().getSaleArea(),projectValue.getYearValueVO().getNotCommodityValue(),projectValue.getYearValueVO().getParkingNum()));
									yearValueVO.setPrice(EmptyUtils.handlePrice(projectValue.getYearValueVO().getHouseCommodityValue(),projectValue.getYearValueVO().getNotCommodityValue()));
									yearValueVO.setActualNum(EmptyUtils.handleNum(projectValue.getYearValueVO().getRoomNumActual(),projectValue.getYearValueVO().getParkingNumActual()));
									yearValueVO.setActualArea(EmptyUtils.handleAreaNullValue(projectValue.getYearValueVO().getAreaActual()));
									yearValueVO.setActualAveragePrice(EmptyUtils.handleAvg(projectValue.getYearValueVO().getHouseCommodityValueActual(),projectValue.getYearValueVO().getAreaActual(),projectValue.getYearValueVO().getNotCommodityValueActual(),projectValue.getYearValueVO().getParkingNumActual()));
									yearValueVO.setActualPrice(EmptyUtils.handlePrice(projectValue.getYearValueVO().getHouseCommodityValueActual(),projectValue.getYearValueVO().getNotCommodityValueActual()));
									//达成率=实际货值/计划货值
									BigDecimal sumPriceActualY = NumberUtils.BigDecimalADD(3,projectValue.getYearValueVO().getHouseCommodityValueActual(),projectValue.getYearValueVO().getNotCommodityValueActual());
									BigDecimal sumPriceY =NumberUtils.BigDecimalADD(3,projectValue.getYearValueVO().getHouseCommodityValue(),projectValue.getYearValueVO().getNotCommodityValue());
									if(sumPriceY == null || sumPriceY.compareTo(BigDecimal.ZERO) == 0) {
										yearValueVO.setAchievingRate("-");
									}else {
										yearValueVO.setAchievingRate(StrUtils.divide(sumPriceActualY+"",sumPriceY+"",4));
									}
									
									//月
									List<ProjectMonthExcelValueVO> proMonthValueList = projectValue.getMonthValueVO();
									if(CollectionUtils.isNotEmpty(proMonthValueList)) {
										for(MonthExcelValueVO month : monthValueVO) {
											for(ProjectMonthExcelValueVO proMonthValue : proMonthValueList) {
												if(month.getMonth().equals(proMonthValue.getMonth())) {
													month.setNum(EmptyUtils.handleNum(proMonthValue.getRoomNum(),proMonthValue.getParkingNum()));
													month.setSaleArea(EmptyUtils.handleAreaNullValue(proMonthValue.getSaleArea()));
													month.setAvgPrice(EmptyUtils.handleAvg(proMonthValue.getHouseCommodityValue(),proMonthValue.getSaleArea(),proMonthValue.getNotCommodityValue(),proMonthValue.getParkingNum()));
													month.setPrice(EmptyUtils.handlePrice(proMonthValue.getHouseCommodityValue(),proMonthValue.getNotCommodityValue()));
													month.setActualNum(EmptyUtils.handleNum(proMonthValue.getRoomNumActual(),proMonthValue.getParkingNumActual()));
													month.setActualArea(EmptyUtils.handleAreaNullValue(proMonthValue.getAreaActual()));
													month.setActualAveragePrice(EmptyUtils.handleAvg(proMonthValue.getHouseCommodityValueActual(),proMonthValue.getAreaActual(),proMonthValue.getNotCommodityValueActual(),proMonthValue.getParkingNumActual()));
													month.setActualPrice(EmptyUtils.handlePrice(proMonthValue.getHouseCommodityValueActual(),proMonthValue.getNotCommodityValueActual()));
													
													//达成率=实际货值/计划货值
													BigDecimal sumPriceActualM = NumberUtils.BigDecimalADD(3,proMonthValue.getHouseCommodityValueActual(),proMonthValue.getNotCommodityValueActual());
													BigDecimal sumPriceM =NumberUtils.BigDecimalADD(3,proMonthValue.getHouseCommodityValue(),proMonthValue.getNotCommodityValue());
													
													if(sumPriceM == null || sumPriceM.compareTo(BigDecimal.ZERO) == 0) {
														month.setAchievingRate("-");
													}else {
														month.setAchievingRate(StrUtils.divide(sumPriceActualM+"",sumPriceM+"",4));
													}
													
												}
											}
										}
									}
								}
							}
						}
						
					}
				}
			}
		}
		
		List<SupplyPlanExcelVO> sortList = sortSupplyPlanExcelData(resList);
		
		OverallSupplyReportTemplate removalReportTemplate = new OverallSupplyReportTemplate(LocalDateTime.now(),yearSet,projectName);
        removalReportTemplate.appendRows(sortList);
        try (OutputStream outputStream = response.getOutputStream()){
        	response.setContentType("application/vnd.ms-excel");
        	response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(projectName+"最新全盘供货计划-".concat(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH"))).concat(".xlsx"), "utf-8"));
            removalReportTemplate.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
        	log.error("#########全盘供货导出异常："+e);
        }
	}

	private List<SupplyPlanExcelVO> sortSupplyPlanExcelData(List<SupplyPlanExcelVO> resList) {
		List<SupplyPlanExcelVO> dataList =  resList.parallelStream().sorted((a, b) -> {
		    //分期
		    String aStageName = StrUtils.nvl(a.getStageName());
		    String bStageName = StrUtils.nvl(b.getStageName());
		    if (!aStageName.equals(bStageName)) {
		    	return ReportUtils.compareStrStartedChinaNum(aStageName, bStageName);
		    }
		    //组团
		    String aGroupName = StrUtils.nvl(a.getGroupName());
		    String bGroupName = StrUtils.nvl(b.getGroupName());
		    if (!aGroupName.equals(bGroupName)) {
		    	return ReportUtils.compareStrStartedChinaNum(aGroupName, bGroupName);
		    }
		    //业态
		    String aProProductName = StrUtils.nvl(a.getProductTypeName());
		    String bProProductName = StrUtils.nvl(b.getProductTypeName());
		    if (!aProProductName.equals(bProProductName)) {
		        return aProProductName.compareTo(bProProductName);
		    }
		    //产品构成
		    String aProductName = StrUtils.nvl(a.getProductName());
		    String bProductName = StrUtils.nvl(b.getProductName());
		    if (!aProductName.equals(bProductName)) {
		        return aProductName.compareTo(bProductName);
		    }
		    //楼栋
		    String aBuildingName = StrUtils.nvl(a.getBulidNo());
            String bBuildingName = StrUtils.nvl(b.getBulidNo());
            if (!aBuildingName.equals(bBuildingName)) {
                return ReportUtils.compareStrStartedChinaNum(aBuildingName, bBuildingName);
            }
		    return 0;
		}).collect(Collectors.toList());
		return dataList;
	}

	private String getBuildPendingHomeSale(String id, List<Map<String, Object>> stagePart) {
		String res = "";
		if(CollectionUtils.isNotEmpty(stagePart)) {
			for(Map<String, Object> map : stagePart) {
				String buildingId = String.valueOf(map.get("building_id"));
				if(id.equals(buildingId)) {
					return String.valueOf(map.get("is_product_exist_room_sale"));
				}
			}
		}
		return res;
	}

	private void setMonthExcelData(List<SupplyPlanVersionDetail> list, MonthExcelValueVO monthValueVO, String id,ProjectExcelValueVO projectData,String year) {
		if(CollectionUtils.isNotEmpty(list)) {
			for(SupplyPlanVersionDetail detail : list) {
				if(detail.getId().equals(id)) {
					monthValueVO.setNum(EmptyUtils.handleNum(detail.getRoomNum(),detail.getParkingNum()));
					monthValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(detail.getSaleArea()));
					monthValueVO.setAvgPrice(EmptyUtils.handleAvg(detail.getHouseCommodityValue(),detail.getSaleArea(),detail.getNotCommodityValue(),detail.getParkingNum()));
					monthValueVO.setPrice(EmptyUtils.handlePrice(detail.getHouseCommodityValue(),detail.getNotCommodityValue()));
					monthValueVO.setActualNum(EmptyUtils.handleNum(detail.getRoomNumActual(),detail.getParkingNumActual()));
					monthValueVO.setActualArea(EmptyUtils.handleAreaNullValue(detail.getAreaActual()));
					monthValueVO.setActualAveragePrice(EmptyUtils.handleAvg(detail.getHouseCommodityValueActual(),detail.getAreaActual(),detail.getNotCommodityValueActual(),detail.getParkingNumActual()));
					monthValueVO.setActualPrice(EmptyUtils.handlePrice(detail.getHouseCommodityValueActual(),detail.getNotCommodityValueActual()));
					
					//达成率=实际货值/计划货值
					BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,detail.getHouseCommodityValueActual(),detail.getNotCommodityValueActual());
					BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,detail.getHouseCommodityValue(),detail.getNotCommodityValue());
					
					if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
						monthValueVO.setAchievingRate("-");
					}else {
						monthValueVO.setAchievingRate(StrUtils.divide(sumPriceActual+"",sumPrice+"",4));
					}
					
					//项目数据
					if(detail.getType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
						List<ProjectYearExcelValueVO> projectValueList = projectData.getYearExcelValueVO();
						if(CollectionUtils.isNotEmpty(projectValueList)) {
							for(ProjectYearExcelValueVO projectYearVo : projectValueList) {
								if(projectYearVo.getYear().equals(year)) {
									List<ProjectMonthExcelValueVO> proMonthValueList = projectYearVo.getMonthValueVO();
									for(ProjectMonthExcelValueVO proMonthExcelValue : proMonthValueList) {
										if(monthValueVO.getMonth().equals(proMonthExcelValue.getMonth())) {
											proMonthExcelValue.setRoomNum(NumberUtils.intADD(proMonthExcelValue.getRoomNum(), detail.getRoomNum()));
											proMonthExcelValue.setParkingNum(NumberUtils.intADD(proMonthExcelValue.getParkingNum(), detail.getParkingNum()));
											proMonthExcelValue.setSaleArea(NumberUtils.BigDecimalADD(2,proMonthExcelValue.getSaleArea(),detail.getSaleArea()));
											proMonthExcelValue.setHouseCommodityValue(NumberUtils.BigDecimalADD(3,proMonthExcelValue.getHouseCommodityValue(),detail.getHouseCommodityValue()));
											proMonthExcelValue.setNotCommodityValue(NumberUtils.BigDecimalADD(3,proMonthExcelValue.getNotCommodityValue(),detail.getNotCommodityValue()));
											proMonthExcelValue.setRoomNumActual(NumberUtils.intADD(proMonthExcelValue.getRoomNumActual(), detail.getRoomNumActual()));
											proMonthExcelValue.setParkingNumActual(NumberUtils.intADD(proMonthExcelValue.getParkingNumActual(), detail.getParkingNumActual()));
											proMonthExcelValue.setAreaActual(NumberUtils.BigDecimalADD(2,proMonthExcelValue.getAreaActual(),detail.getAreaActual()));
											proMonthExcelValue.setHouseCommodityValueActual(NumberUtils.BigDecimalADD(3,proMonthExcelValue.getHouseCommodityValueActual(),detail.getHouseCommodityValueActual()));
											proMonthExcelValue.setNotCommodityValueActual(NumberUtils.BigDecimalADD(3,proMonthExcelValue.getNotCommodityValueActual(),detail.getNotCommodityValueActual()));
										}
									}
								}
							}
						}
					}
				}
			}
		}
		
	}

	private ProjectExcelValueVO initProject(Set<String> yearSet) {
		ProjectExcelValueVO projectData = new ProjectExcelValueVO();
		projectData.setOverAllValueVO(new ProjectBaseExcelValueVO());
		List<ProjectYearExcelValueVO> proYearExcelValueList = Collections.synchronizedList(new ArrayList<>());
		for(String year : yearSet) {
			ProjectYearExcelValueVO yearVo = new ProjectYearExcelValueVO();
			yearVo.setYear(year);
			yearVo.setYearValueVO(new ProjectBaseExcelValueVO());
			List<ProjectMonthExcelValueVO> monthValueList = getProMonthExcelValue(year);
			yearVo.setMonthValueVO(monthValueList);
			proYearExcelValueList.add(yearVo);
		}
		projectData.setYearExcelValueVO(proYearExcelValueList);
		return projectData;
	}
	
	private void prepareProjectData(List<SupplyPlanExcelVO> resList,MdmProject project,Set<String> yearSet) {
		SupplyPlanExcelVO vo = new SupplyPlanExcelVO();
		vo.setId(project.getProjectId());
		vo.setPid(Constants.ROOT_NODE_PID);
		vo.setType(OrgTypeEunm.ORG_PRODUCTF.getKey());
		vo.setProjectName(project.getProjectName());
		vo.setProjectCode(project.getProjectCode());
		List<YearExcelValueVO> yearExcelValueList = Collections.synchronizedList(new ArrayList<>());
		for(String year : yearSet) {
			YearExcelValueVO yearExcelValue = new YearExcelValueVO();
			BaseExcelValueVO yearValue = new BaseExcelValueVO();
			List<MonthExcelValueVO> monthValue = getMonthExcelValue(year);
			yearExcelValue.setYear(year);
			yearExcelValue.setYearValueVO(yearValue);
			yearExcelValue.setMonthValueVO(monthValue);
			yearExcelValueList.add(yearExcelValue);
		}
		vo.setOverAllValueVO(new BaseExcelValueVO());
		vo.setYearExcelValueVO(yearExcelValueList);
		resList.add(vo);
	}
	
	private BaseExcelValueVO setYearValue(SupplyPlanVersionDetail detail,ProjectExcelValueVO projectData,String year) {
		BaseExcelValueVO overAllValueVO = new BaseExcelValueVO();
		overAllValueVO.setNum(EmptyUtils.handleNum(detail.getRoomNum(),detail.getParkingNum()));
		overAllValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(detail.getSaleArea()));
		overAllValueVO.setAvgPrice(EmptyUtils.handleAvg(detail.getHouseCommodityValue(),detail.getSaleArea(),detail.getNotCommodityValue(),detail.getParkingNum()));
		overAllValueVO.setPrice(EmptyUtils.handlePrice(detail.getHouseCommodityValue(),detail.getNotCommodityValue()));
		overAllValueVO.setActualNum(EmptyUtils.handleNum(detail.getRoomNumActual(),detail.getParkingNumActual()));
		overAllValueVO.setActualArea(EmptyUtils.handleAreaNullValue(detail.getAreaActual()));
		overAllValueVO.setActualAveragePrice(EmptyUtils.handleAvg(detail.getHouseCommodityValueActual(),detail.getAreaActual(),detail.getNotCommodityValueActual(),detail.getParkingNumActual()));
		overAllValueVO.setActualPrice(EmptyUtils.handlePrice(detail.getHouseCommodityValueActual(),detail.getNotCommodityValueActual()));
		//达成率=实际货值/计划货值
		BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,detail.getHouseCommodityValueActual(),detail.getNotCommodityValueActual());
		BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,detail.getHouseCommodityValue(),detail.getNotCommodityValue());
		if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
			overAllValueVO.setAchievingRate("-");
		}else {
			overAllValueVO.setAchievingRate(StrUtils.divide(sumPriceActual+"",sumPrice+"",4));
		}
		//项目数据
		if(detail.getType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
			List<ProjectYearExcelValueVO> projectValueList = projectData.getYearExcelValueVO();
			if(CollectionUtils.isNotEmpty(projectValueList)) {
				for(ProjectYearExcelValueVO projectYearVo : projectValueList) {
					if(projectYearVo.getYear().equals(year)) {
						ProjectBaseExcelValueVO yearValueVO = projectYearVo.getYearValueVO();
						yearValueVO.setRoomNum(NumberUtils.intADD(yearValueVO.getRoomNum(), detail.getRoomNum()));
						yearValueVO.setParkingNum(NumberUtils.intADD(yearValueVO.getParkingNum(), detail.getParkingNum()));
						yearValueVO.setSaleArea(NumberUtils.BigDecimalADD(2,yearValueVO.getSaleArea(),detail.getSaleArea()));
						yearValueVO.setHouseCommodityValue(NumberUtils.BigDecimalADD(3,yearValueVO.getHouseCommodityValue(),detail.getHouseCommodityValue()));
						yearValueVO.setNotCommodityValue(NumberUtils.BigDecimalADD(3,yearValueVO.getNotCommodityValue(),detail.getNotCommodityValue()));
						yearValueVO.setRoomNumActual(NumberUtils.intADD(yearValueVO.getRoomNumActual(), detail.getRoomNumActual()));
						yearValueVO.setParkingNumActual(NumberUtils.intADD(yearValueVO.getParkingNumActual(), detail.getParkingNumActual()));
						yearValueVO.setAreaActual(NumberUtils.BigDecimalADD(2,yearValueVO.getAreaActual(),detail.getAreaActual()));
						yearValueVO.setHouseCommodityValueActual(NumberUtils.BigDecimalADD(3,yearValueVO.getHouseCommodityValueActual(),detail.getHouseCommodityValueActual()));
						yearValueVO.setNotCommodityValueActual(NumberUtils.BigDecimalADD(3,yearValueVO.getNotCommodityValueActual(),detail.getNotCommodityValueActual()));
					}
				}
			}
		}
		return overAllValueVO;
	}
	
	private BaseExcelValueVO setOverAllValue(SupplyPlanVersionDetail all,ProjectExcelValueVO projectData) {
		BaseExcelValueVO overAllValueVO = new BaseExcelValueVO();
		overAllValueVO.setNum(EmptyUtils.handleNum(all.getRoomNum(),all.getParkingNum()));
		overAllValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(all.getSaleArea()));
		overAllValueVO.setAvgPrice(EmptyUtils.handleAvg(all.getHouseCommodityValue(),all.getSaleArea(),all.getNotCommodityValue(),all.getParkingNum()));
		overAllValueVO.setPrice(EmptyUtils.handlePrice(all.getHouseCommodityValue(),all.getNotCommodityValue()));
		overAllValueVO.setActualNum(EmptyUtils.handleNum(all.getRoomNumActual(),all.getParkingNumActual()));
		overAllValueVO.setActualArea(EmptyUtils.handleAreaNullValue(all.getAreaActual()));
		overAllValueVO.setActualAveragePrice(EmptyUtils.handleAvg(all.getHouseCommodityValueActual(),all.getAreaActual(),all.getNotCommodityValueActual(),all.getParkingNumActual()));
		overAllValueVO.setActualPrice(EmptyUtils.handlePrice(all.getHouseCommodityValueActual(),all.getNotCommodityValueActual()));
		//达成率=实际货值/计划货值
		BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,all.getHouseCommodityValueActual(),all.getNotCommodityValueActual());
		BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,all.getHouseCommodityValue(),all.getNotCommodityValue());
		
		if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
			overAllValueVO.setAchievingRate("-");
		}else {
			overAllValueVO.setAchievingRate(StrUtils.divide(sumPriceActual+"",sumPrice+"",4));
		}
		
		
		//项目数据
		if(all.getType().equals(OrgTypeEunm.ORG_STAGE.getKey())) {
			ProjectBaseExcelValueVO project = projectData.getOverAllValueVO();
			if(project != null) {
				project.setRoomNum(NumberUtils.intADD(project.getRoomNum(), all.getRoomNum()));
				project.setParkingNum(NumberUtils.intADD(project.getParkingNum(), all.getParkingNum()));
				project.setSaleArea(NumberUtils.BigDecimalADD(2,project.getSaleArea(),all.getSaleArea()));
				project.setHouseCommodityValue(NumberUtils.BigDecimalADD(3,project.getHouseCommodityValue(),all.getHouseCommodityValue()));
				project.setNotCommodityValue(NumberUtils.BigDecimalADD(3,project.getNotCommodityValue(),all.getNotCommodityValue()));
				
				project.setRoomNumActual(NumberUtils.intADD(project.getRoomNumActual(), all.getRoomNumActual()));
				project.setParkingNumActual(NumberUtils.intADD(project.getParkingNumActual(), all.getParkingNumActual()));
				project.setAreaActual(NumberUtils.BigDecimalADD(2,project.getAreaActual(),all.getAreaActual()));
				project.setHouseCommodityValueActual(NumberUtils.BigDecimalADD(3,project.getHouseCommodityValueActual(),all.getHouseCommodityValueActual()));
				project.setNotCommodityValueActual(NumberUtils.BigDecimalADD(3,project.getNotCommodityValueActual(),all.getNotCommodityValueActual()));
			}
		}
		return overAllValueVO;
	}

	private void prepareGroupParentInfo(List<SupplyPlanVersionDetail> list, String pId, SupplyPlanExcelVO vo,List<Map<String, Object>> stagePart, StagePartNers stagePartNers) {
		//分期信息
		SupplyPlanVersionDetail stageDetail = getParentData(list,pId);
		if(stageDetail != null) {
			vo.setStageName(stageDetail.getOrgName());
			vo.setStageCode(stageDetail.getOrgCode());
			prepareStageData(vo, stagePart, stagePartNers);
		}
	}
	
	private void prepareProductParentInfo(List<SupplyPlanVersionDetail> all,String pId, SupplyPlanExcelVO vo,List<Map<String, Object>> stagePart, StagePartNers stagePartNers) {
		SupplyPlanVersionDetail gDetail = getParentData(all,pId);
		if(gDetail != null) {
			vo.setGroupName(gDetail.getOrgName());
			//分期信息
			SupplyPlanVersionDetail sDetail = getParentData(all,gDetail.getPid());
			if(sDetail != null) {
				vo.setStageName(sDetail.getOrgName());
				vo.setStageCode(sDetail.getOrgCode());
				prepareStageData(vo, stagePart, stagePartNers);
			}
		}
	}
	
	private void prepareBuildParentInfo(List<SupplyPlanVersionDetail> list, String pId, SupplyPlanExcelVO vo,List<Map<String, Object>> stagePart, StagePartNers stagePartNers) {
		SupplyPlanVersionDetail pDetail = getParentData(list,pId);
		if(pDetail != null) {
			//产品信息
			vo.setProductTypeName(pDetail.getProProductType());
			vo.setProductTypeCode(pDetail.getProProductCode());
			vo.setProductName(pDetail.getOrgName());
			vo.setProductCode(pDetail.getOrgCode());
			//组团信息
			SupplyPlanVersionDetail gDetail = getParentData(list,pDetail.getPid());
			if(gDetail != null) {
				vo.setGroupName(gDetail.getOrgName());
				//分期信息
				SupplyPlanVersionDetail sDetail = getParentData(list,gDetail.getPid());
				if(sDetail != null) {
					vo.setStageName(sDetail.getOrgName());
					vo.setStageCode(sDetail.getOrgCode());
					prepareStageData(vo, stagePart, stagePartNers);
				}
			}
		}
		
	}
	
	private void prepareStageData(SupplyPlanExcelVO vo, List<Map<String, Object>> stagePart, StagePartNers stagePartNers) {
		if(CollectionUtils.isNotEmpty(stagePart)) {
			vo.setPendingHomeSale(stagePart.get(0).get("is_exist_room_sale")+"");
		}
		if (stagePartNers != null){
			vo.setEquityRatio(stagePartNers.getEquityRatio());
			vo.setTradersWay(stagePartNers.getIsOpMarketing());
			vo.setIsMergeTable(stagePartNers.getPartNerIsAndTable());
		}
	}
	
	private SupplyPlanVersionDetail getParentData(List<SupplyPlanVersionDetail> list,String pId) {
		if(CollectionUtils.isNotEmpty(list)) {
			for(SupplyPlanVersionDetail detail : list) {
				if(detail.getId().equals(pId)) {
					return detail;
				}
			}
		}
		return null;
	}
	
	@Override
	public R overAllYears(String apiVersion, String projectId) {
		Set<String> yearSet = getYears(projectId);
		return ok(yearSet);
	}

	private Set<String> getYears(String projectId) {
		List<Map<String, Object>> years = supplyPlanVersionDetailService.queryYears(projectId);
		Set<String> yearSet =  new TreeSet<>(); 
		if(CollectionUtils.isNotEmpty(years)) {
			years.forEach(map->{
				if(map != null) {
					String supplyDate = String.valueOf(map.get("supply_date"));
					String supplyDateActual = String.valueOf(map.get("supply_date_actual"));
					if(StrUtils.isNotEmpty(supplyDate)) {
						yearSet.add(supplyDate);
					}
					if(StrUtils.isNotEmpty(supplyDateActual)) {
						yearSet.add(supplyDateActual);
					}
				}
			});
		}
		return yearSet;
	}
	
	@Override
	public R overAllValue(String apiVersion, String projectId,String year,String type,String code) {
		List<SupplyPlanOverAllValueDataVO> dataList = handleSupplyPlanOverAllValueData(projectId,year,code);
		saveLog("供货计划","全盘供货计划","查看全盘供货计划");
		return ok(dataList);
	}
	
	/**
	 * 房源标识
	 */
	private static final String HOUSE_KEY  = "house";
	/**
	 * 车位标识
	 */
	private static final String PARKING_KEY  = "parking";
	
	/**
	 * 
	 * @Description：获取供货全盘最新版本
	 * @author：yyd
	 * @date：2020年2月6日 上午10:43:12
	 */
	private List<SupplyPlanVersion> getNewestVersion(String projectId,String stageName) {
		List<SupplyPlanVersion> supplyPlanVersionList =Collections.synchronizedList(new ArrayList<>());
		//1、获取项目下各个分期
		List<SupplyPlanVersion> stageList = supplyPlanVersionService.queryNewestVersionByProjectId(projectId,stageName);
		//2、获取各分期下最新的版本（基于货值版本的最新版本）
		if(CollectionUtils.isNotEmpty(stageList)) {
			for(SupplyPlanVersion supplyPlanVersion : stageList) {
				String stageId = supplyPlanVersion.getProjectfId();
				boolean isActiveStage = stageService.isActiveStage(stageId);
				if(!isActiveStage) {
					continue;
				}
				PriceVersion priceVersion  = priceVersionService.getNewestPriceVersion(stageId);
				if(priceVersion != null) {
					SupplyPlanVersion obj = supplyPlanVersionService.selectNewestVersionByPriceId(priceVersion.getId());
					if(obj != null) {
						supplyPlanVersionList.add(obj);
					}
				}
			}
		}
		return supplyPlanVersionList;
	}
	/**
	 * 
	 * @Description：全盘供货计划数据处理
	 * @author：yyd
	 * @date：2020年2月6日 上午10:43:38
	 */
	private List<SupplyPlanOverAllValueDataVO> handleSupplyPlanOverAllValueData(String projectId,String year,String name) {
		List<SupplyPlanOverAllValueDataVO> resList = Collections.synchronizedList(new ArrayList<>());
		String stageName = StrUtils.getStageCondition(name);
		List<SupplyPlanVersion> supplyPlanVersionList =getNewestVersion(projectId,stageName);
		//3、获取各分期下最新的版本详情
		for(SupplyPlanVersion supplyPlanVersion : supplyPlanVersionList) {
			List<SupplyPlanOverAllValueDataVO> dataList = Collections.synchronizedList(new ArrayList<>());
			String versionId = supplyPlanVersion.getId();
			String versionName = prepareVersionName(supplyPlanVersion);
			//获取版本阶段
			String versionType = supplyPlanVersion.getVersionType();
			//处理筛选条件
			String code = StrUtils.prepareOverCondition(name,versionType);
			List<SupplyPlanVersionDetail> allList = supplyPlanVersionDetailService.queryByVersionId(versionId);
			
			//全盘
			List<SupplyPlanVersionDetail> list = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(allList,versionType,versionId,code,"","");
			//年度
			List<SupplyPlanVersionDetail> yearList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,"");
			//年度月份
			List<SupplyPlanVersionDetail> oneList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.january.getValue());
		    List<SupplyPlanVersionDetail> twoList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.february.getValue());
			List<SupplyPlanVersionDetail> threeList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.march.getValue());
			List<SupplyPlanVersionDetail> fourList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.april.getValue());
			List<SupplyPlanVersionDetail> fiveList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.may.getValue());
			List<SupplyPlanVersionDetail> sixList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.june.getValue());
			List<SupplyPlanVersionDetail> sevenList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.july.getValue());
			List<SupplyPlanVersionDetail> eigthList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.august.getValue());
			List<SupplyPlanVersionDetail> nineList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.september.getValue());
			List<SupplyPlanVersionDetail> tenList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.october.getValue());
			List<SupplyPlanVersionDetail> elevenList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.november.getValue());
			List<SupplyPlanVersionDetail> twelevList = supplyPlanVersionDetailService.collectSupplyPlanVersionDetailList(list,versionType,versionId,code,year,MonthEnum.december.getValue());
			
			if(CollectionUtils.isNotEmpty(list)) {
				list.forEach(x->{
					SupplyPlanOverAllValueDataVO vo = new SupplyPlanOverAllValueDataVO();
					vo.setId(x.getId());
					vo.setCode(x.getOrgCode());
					if(x.getPid().equals(Constants.ROOT_NODE_PID)) {
						vo.setName(x.getOrgName()+"("+versionName+")");
					}else {
						vo.setName(x.getOrgName());
					}
					vo.setType(x.getType());
					vo.setPid(x.getPid());
					vo.setProProductCode(x.getProProductCode());
					vo.setProProductName(x.getProProductType());
					vo.setIsSupply(x.getIsSupply());
					vo.setIsDelay(x.getIsDelay());
					vo.setIsParking(x.getIsParking());
					//全盘供货计划与实际
					BaseValueVO overAllValueVO = new BaseValueVO();
					overAllValueVO.setNum(EmptyUtils.handleNumNullValue(x.getNums()));
					overAllValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(x.getSaleArea()));
					overAllValueVO.setAvgPrice(EmptyUtils.handleAvgNullValue2(x.getAvgPrice()));
					overAllValueVO.setPrice(EmptyUtils.handlePriceNullValue2(x.getPrice()));
					if(!versionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
						overAllValueVO.setActualNum(EmptyUtils.handleNumNullValue(x.getNumsActual()));
						overAllValueVO.setActualArea(EmptyUtils.handleAreaNullValue(x.getAreaActual()));
						overAllValueVO.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(x.getAvgPriceActual()));
						overAllValueVO.setActualPrice(EmptyUtils.handlePriceNullValue2(x.getPriceActual()));
						overAllValueVO.setAchievingRate(x.getValueAchievingRate());
					}
					vo.setOverAllValueVO(overAllValueVO);
					//年度供货合计
					BaseValueVO yearValueVO = initYearValue();
					for(SupplyPlanVersionDetail yearObj : yearList) {
						if(x.getId().equals(yearObj.getId())) {
							yearValueVO.setNum(EmptyUtils.handleNumNullValue(yearObj.getNums()));
							yearValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(yearObj.getSaleArea()));
							yearValueVO.setAvgPrice(EmptyUtils.handleAvgNullValue2(yearObj.getAvgPrice()));
							yearValueVO.setPrice(EmptyUtils.handlePriceNullValue2(yearObj.getPrice()));
							if(!versionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
								yearValueVO.setActualNum(EmptyUtils.handleNumNullValue(yearObj.getNumsActual()));
								yearValueVO.setActualArea(EmptyUtils.handleAreaNullValue(yearObj.getAreaActual()));
								yearValueVO.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(yearObj.getAvgPriceActual()));
								yearValueVO.setActualPrice(EmptyUtils.handlePriceNullValue2(yearObj.getPriceActual()));
								yearValueVO.setAchievingRate(yearObj.getValueAchievingRate());
							}
						}
					}
					vo.setYearValueVO(yearValueVO);
					//月度（每月）
					List<MonthValueVO> monthValue = initMonthValue(year);
					for(MonthValueVO monthValueVO : monthValue) {
						int monthTemp = Integer.parseInt(monthValueVO.getName().split("-")[1]);
						switch (monthTemp) {
						case 1:
							setMonthData(oneList,monthValueVO,x.getId(),versionType);
							break;
						case 2:
							setMonthData(twoList,monthValueVO,x.getId(),versionType);
							break;
						case 3:
							setMonthData(threeList,monthValueVO,x.getId(),versionType);
							break;
						case 4:
							setMonthData(fourList,monthValueVO,x.getId(),versionType);
							break;
						case 5:
							setMonthData(fiveList,monthValueVO,x.getId(),versionType);
							break;
						case 6:
							setMonthData(sixList,monthValueVO,x.getId(),versionType);
							break;
						case 7:
							setMonthData(sevenList,monthValueVO,x.getId(),versionType);
							break;
						case 8:
							setMonthData(eigthList,monthValueVO,x.getId(),versionType);
							break;
						case 9:
							setMonthData(nineList,monthValueVO,x.getId(),versionType);
							break;
						case 10:
							setMonthData(tenList,monthValueVO,x.getId(),versionType);
							break;
						case 11:
							setMonthData(elevenList,monthValueVO,x.getId(),versionType);
							break;
						case 12:
							setMonthData(twelevList,monthValueVO,x.getId(),versionType);
							break;
						default:
							break;
						}
					}
					vo.setMonthValue(monthValue);
					dataList.add(vo);
				});
			}
			//全盘供货计划层级数据排序
			List<SupplyPlanOverAllValueDataVO> sortList = overAllVersionDetailSort(dataList);
			resList.addAll(sortList);
		}
		
		//添加项目层级 并归集数据
		if(CollectionUtils.isNotEmpty(resList)) {
			ProjectValueVO tempVO = new ProjectValueVO();
			for(SupplyPlanOverAllValueDataVO vo : resList) {
				String pid = vo.getPid();
				if(pid.equals(Constants.ROOT_NODE_PID)) {
					vo.setPid(projectId);
					//1、全盘
					BaseValueVO overAllValueVO = vo.getOverAllValueVO();
					int roomNum = getNum(overAllValueVO.getNum(),HOUSE_KEY);
					int pNum = getNum(overAllValueVO.getNum(),PARKING_KEY);
					BigDecimal rPrice = getPrice(overAllValueVO.getPrice(),HOUSE_KEY);
					BigDecimal pPrice = getPrice(overAllValueVO.getPrice(),PARKING_KEY);
					
					int roomNuma = getNum(overAllValueVO.getActualNum(),HOUSE_KEY);
					int pNuma = getNum(overAllValueVO.getActualNum(),PARKING_KEY);
					BigDecimal rPricea = getPrice(overAllValueVO.getActualPrice(),HOUSE_KEY);
					BigDecimal pPricea = getPrice(overAllValueVO.getActualPrice(),PARKING_KEY);
				
					tempVO.setRoomNum(tempVO.getRoomNum()+roomNum);
					tempVO.setParkingNum(tempVO.getParkingNum()+pNum);
					tempVO.setSaleArea(tempVO.getSaleArea().add(NumberUtils.strToBigDecimal(overAllValueVO.getSaleArea())));
					tempVO.setHousePrice(tempVO.getHousePrice().add(rPrice));
					tempVO.setParkingPrice(tempVO.getParkingPrice().add(pPrice));
					tempVO.setActualRoomNum(tempVO.getActualRoomNum()+roomNuma);
					tempVO.setActualParkingNum(tempVO.getActualParkingNum()+pNuma);
					tempVO.setActualArea(tempVO.getActualArea().add(NumberUtils.strToBigDecimal(overAllValueVO.getActualArea())));
					tempVO.setActualHousePrice(tempVO.getActualHousePrice().add(rPricea));
					tempVO.setActualParkingPrice(tempVO.getActualParkingPrice().add(pPricea));
					//年度
					BaseValueVO yearValueVO = vo.getYearValueVO();
					int yroomNum = getNum(yearValueVO.getNum(),HOUSE_KEY);
					int ypNum = getNum(yearValueVO.getNum(),PARKING_KEY);
					BigDecimal yrPrice = getPrice(yearValueVO.getPrice(),HOUSE_KEY);
					BigDecimal ypPrice = getPrice(yearValueVO.getPrice(),PARKING_KEY);
					
					int yroomNuma = getNum(yearValueVO.getActualNum(),HOUSE_KEY);
					int ypNuma = getNum(yearValueVO.getActualNum(),PARKING_KEY);
					BigDecimal yrPricea = getPrice(yearValueVO.getActualPrice(),HOUSE_KEY);
					BigDecimal ypPricea = getPrice(yearValueVO.getActualPrice(),PARKING_KEY);
				
					tempVO.getYearValueVO().setRoomNum(tempVO.getYearValueVO().getRoomNum()+yroomNum);
					tempVO.getYearValueVO().setParkingNum(tempVO.getYearValueVO().getParkingNum()+ypNum);
					tempVO.getYearValueVO().setSaleArea(tempVO.getYearValueVO().getSaleArea().add(NumberUtils.strToBigDecimal(yearValueVO.getSaleArea())));
					tempVO.getYearValueVO().setHousePrice(tempVO.getYearValueVO().getHousePrice().add(yrPrice));
					tempVO.getYearValueVO().setParkingPrice(tempVO.getYearValueVO().getParkingPrice().add(ypPrice));
					tempVO.getYearValueVO().setActualRoomNum(tempVO.getYearValueVO().getActualRoomNum()+yroomNuma);
					tempVO.getYearValueVO().setActualParkingNum(tempVO.getYearValueVO().getActualParkingNum()+ypNuma);
					tempVO.getYearValueVO().setActualArea(tempVO.getYearValueVO().getActualArea().add(NumberUtils.strToBigDecimal(yearValueVO.getActualArea())));
					tempVO.getYearValueVO().setActualHousePrice(tempVO.getYearValueVO().getActualHousePrice().add(yrPricea));
					tempVO.getYearValueVO().setActualParkingPrice(tempVO.getYearValueVO().getActualParkingPrice().add(ypPricea));
					
					//月度
					List<MonthValueVO> monthValueList = vo.getMonthValue();
					for(MonthValueVO monthValueVO : monthValueList) {
						for(ProjectMonthValueVO projectMonthValueVO : tempVO.getMonthValue(year)) {
							if(monthValueVO.getName().equals(projectMonthValueVO.getName())) {
								int mroomNum =getNum(monthValueVO.getNum(),HOUSE_KEY);
								int mpNum = getNum(monthValueVO.getNum(),PARKING_KEY);
								BigDecimal mrPrice =getPrice(monthValueVO.getPrice(),HOUSE_KEY);
								BigDecimal mpPrice = getPrice(monthValueVO.getPrice(),PARKING_KEY);
								
								int mroomNuma = getNum(monthValueVO.getActualNum(),HOUSE_KEY);
								int mpNuma = getNum(monthValueVO.getActualNum(),PARKING_KEY);
								BigDecimal mrPricea =getPrice(monthValueVO.getActualPrice(),HOUSE_KEY);
								BigDecimal mpPricea = getPrice(monthValueVO.getActualPrice(),PARKING_KEY);
							
								projectMonthValueVO.setRoomNum(projectMonthValueVO.getRoomNum()+mroomNum);
								projectMonthValueVO.setParkingNum(projectMonthValueVO.getParkingNum()+mpNum);
								projectMonthValueVO.setSaleArea(projectMonthValueVO.getSaleArea().add(NumberUtils.strToBigDecimal(monthValueVO.getSaleArea())));
								projectMonthValueVO.setHousePrice(projectMonthValueVO.getHousePrice().add(mrPrice));
								projectMonthValueVO.setParkingPrice(projectMonthValueVO.getParkingPrice().add(mpPrice));
								projectMonthValueVO.setActualRoomNum(projectMonthValueVO.getActualRoomNum()+mroomNuma);
								projectMonthValueVO.setActualParkingNum(projectMonthValueVO.getActualParkingNum()+mpNuma);
								projectMonthValueVO.setActualArea(projectMonthValueVO.getActualArea().add(NumberUtils.strToBigDecimal(monthValueVO.getActualArea())));
								projectMonthValueVO.setActualHousePrice(projectMonthValueVO.getActualHousePrice().add(mrPricea));
								projectMonthValueVO.setActualParkingPrice(projectMonthValueVO.getActualParkingPrice().add(mpPricea));
							}
						}
					}
					
				}
			}
			//获取项目信息
			MdmProject project = projectService.selectByProjectId(projectId, IsDeleteEnum.NO.getKey());
			SupplyPlanOverAllValueDataVO projectVo = getProjectLevel(year);
			projectVo.setId(projectId);
			projectVo.setCode(project.getProjectCode());
			projectVo.setName(project.getProjectName());
			projectVo.setPid(Constants.ROOT_NODE_PID);
			projectVo.setType("");
			//1、全盘
			BaseValueVO overAllValueVO = projectVo.getOverAllValueVO();
			overAllValueVO.setNum(EmptyUtils.handleNumNullValue(tempVO.getRoomNum()+" / "+tempVO.getParkingNum()));
			overAllValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(tempVO.getSaleArea()));
			overAllValueVO.setAvgPrice(EmptyUtils.handleAvgNullValue2(StrUtils.divide(tempVO.getHousePrice(),tempVO.getSaleArea())+" / "+StrUtils.divide(tempVO.getParkingPrice(),new BigDecimal(tempVO.getParkingNum()))));
			overAllValueVO.setPrice(EmptyUtils.handlePriceNullValue2(NumberUtils.BigDecimalADD(4,tempVO.getHousePrice(), tempVO.getParkingPrice())+" / "+tempVO.getHousePrice()+" / "+tempVO.getParkingPrice()));
			overAllValueVO.setActualNum(EmptyUtils.handleNumNullValue(tempVO.getActualRoomNum()+" / "+tempVO.getActualParkingNum()));
			overAllValueVO.setActualArea(EmptyUtils.handleAreaNullValue(tempVO.getActualArea()));
			overAllValueVO.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(StrUtils.divide(tempVO.getActualHousePrice(),tempVO.getActualArea())+" / "+StrUtils.divide(tempVO.getActualParkingPrice(),new BigDecimal(tempVO.getActualParkingNum()))));
			overAllValueVO.setActualPrice(EmptyUtils.handlePriceNullValue2(NumberUtils.BigDecimalADD(4,tempVO.getActualHousePrice(),tempVO.getActualParkingPrice())+" / "+tempVO.getActualHousePrice()+" / "+tempVO.getActualParkingPrice()));
			//达成率=实际货值（房源货值+不含未推售车位货值）/计划货值（房源货值+不含未推售车位货值）
			BigDecimal sumPriceActual = NumberUtils.BigDecimalADD(3,tempVO.getActualHousePrice(), tempVO.getActualParkingPrice());
			BigDecimal sumPrice =NumberUtils.BigDecimalADD(3,tempVO.getHousePrice(),tempVO.getParkingPrice());
			if(sumPrice == null || sumPrice.compareTo(BigDecimal.ZERO) == 0) {
				overAllValueVO.setAchievingRate("-");
			}else {
				overAllValueVO.setAchievingRate(StrUtils.divide(sumPriceActual+"",sumPrice+"",4));
			}
//			projectVo.setOverAllValueVO(overAllValueVO);
			//年度
			BaseValueVO yearValueVO = projectVo.getYearValueVO();
			yearValueVO.setNum(EmptyUtils.handleNumNullValue(tempVO.getYearValueVO().getRoomNum()+" / "+tempVO.getYearValueVO().getParkingNum()));
			yearValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(tempVO.getYearValueVO().getSaleArea()));
			yearValueVO.setAvgPrice(EmptyUtils.handleAvgNullValue2(StrUtils.divide(tempVO.getYearValueVO().getHousePrice(),tempVO.getYearValueVO().getSaleArea())+" / "+StrUtils.divide(tempVO.getYearValueVO().getParkingPrice(),new BigDecimal(tempVO.getYearValueVO().getParkingNum()))));
			yearValueVO.setPrice(EmptyUtils.handlePriceNullValue2(NumberUtils.BigDecimalADD(4,tempVO.getYearValueVO().getHousePrice(),tempVO.getYearValueVO().getParkingPrice())+" / "+tempVO.getYearValueVO().getHousePrice()+" / "+tempVO.getYearValueVO().getParkingPrice()));
			yearValueVO.setActualNum(EmptyUtils.handleNumNullValue(tempVO.getYearValueVO().getActualRoomNum()+" / "+tempVO.getYearValueVO().getActualParkingNum()));
			yearValueVO.setActualArea(EmptyUtils.handleAreaNullValue(tempVO.getYearValueVO().getActualArea()));
			yearValueVO.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(StrUtils.divide(tempVO.getYearValueVO().getActualHousePrice(),tempVO.getYearValueVO().getActualArea())+" / "+StrUtils.divide(tempVO.getYearValueVO().getActualParkingPrice(),new BigDecimal(tempVO.getYearValueVO().getActualParkingNum()))));
			yearValueVO.setActualPrice(EmptyUtils.handlePriceNullValue2(NumberUtils.BigDecimalADD(4,tempVO.getYearValueVO().getActualHousePrice(),tempVO.getYearValueVO().getActualParkingPrice())+" / "+tempVO.getYearValueVO().getActualHousePrice()+" / "+tempVO.getYearValueVO().getActualParkingPrice()));
			//达成率=实际货值（房源货值+不含未推售车位货值）/计划货值（房源货值+不含未推售车位货值）
			BigDecimal sumYPriceActual = NumberUtils.BigDecimalADD(3,tempVO.getYearValueVO().getActualHousePrice(), tempVO.getYearValueVO().getActualParkingPrice());
			BigDecimal sumYPrice =NumberUtils.BigDecimalADD(3,tempVO.getYearValueVO().getHousePrice(),tempVO.getYearValueVO().getParkingPrice());
			
			if(sumYPrice == null || sumYPrice.compareTo(BigDecimal.ZERO) == 0) {
				yearValueVO.setAchievingRate("-");
			}else {
				yearValueVO.setAchievingRate(StrUtils.divide(sumYPriceActual+"",sumYPrice+"",4));
			}
//			projectVo.setYearValueVO(yearValueVO);
			//月度
			List<MonthValueVO> monthValueList = projectVo.getMonthValue();
			for(MonthValueVO monthValueVO : monthValueList) {
				for(ProjectMonthValueVO projectMonthValueVO : tempVO.getMonthValue(year)) {
					if(monthValueVO.getName().equals(projectMonthValueVO.getName())) {
						monthValueVO.setNum(EmptyUtils.handleNumNullValue(projectMonthValueVO.getRoomNum()+" / "+projectMonthValueVO.getParkingNum()));
						monthValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(projectMonthValueVO.getSaleArea()));
						monthValueVO.setAvgPrice(EmptyUtils.handleAvgNullValue2(StrUtils.divide(projectMonthValueVO.getHousePrice(),projectMonthValueVO.getSaleArea())+" / "+StrUtils.divide(projectMonthValueVO.getParkingPrice(),new BigDecimal(projectMonthValueVO.getParkingNum()))));
						monthValueVO.setPrice(EmptyUtils.handlePriceNullValue2(NumberUtils.BigDecimalADD(4,projectMonthValueVO.getHousePrice(),projectMonthValueVO.getParkingPrice())+" / "+projectMonthValueVO.getHousePrice()+" / "+projectMonthValueVO.getParkingPrice()));
						monthValueVO.setActualNum(EmptyUtils.handleNumNullValue(projectMonthValueVO.getActualRoomNum()+" / "+projectMonthValueVO.getActualParkingNum()));
						monthValueVO.setActualArea(EmptyUtils.handleAreaNullValue(projectMonthValueVO.getActualArea()));
						monthValueVO.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(StrUtils.divide(projectMonthValueVO.getActualHousePrice(),projectMonthValueVO.getActualArea())+" / "+StrUtils.divide(projectMonthValueVO.getActualParkingPrice(),new BigDecimal(projectMonthValueVO.getActualParkingNum()))));
						monthValueVO.setActualPrice(EmptyUtils.handlePriceNullValue2(NumberUtils.BigDecimalADD(4,projectMonthValueVO.getActualHousePrice(),projectMonthValueVO.getActualParkingPrice())+" / "+projectMonthValueVO.getActualHousePrice()+" / "+projectMonthValueVO.getActualParkingPrice()));
						//达成率=实际货值（房源货值+不含未推售车位货值）/计划货值（房源货值+不含未推售车位货值）
						BigDecimal sumMPriceActual = NumberUtils.BigDecimalADD(3,projectMonthValueVO.getActualHousePrice(), projectMonthValueVO.getActualParkingPrice());
						BigDecimal sumMPrice =NumberUtils.BigDecimalADD(3,projectMonthValueVO.getHousePrice(),projectMonthValueVO.getParkingPrice());
						if(sumMPrice == null || sumMPrice.compareTo(BigDecimal.ZERO) == 0) {
							monthValueVO.setAchievingRate("-");
						}else {
							monthValueVO.setAchievingRate(StrUtils.divide(sumMPriceActual+"",sumMPrice+"",4));
						}
					}
				}
			}
//			projectVo.setMonthValue(monthValueList);
			resList.add(projectVo);
		}
		
		//分期排序
		List<SupplyPlanOverAllValueDataVO> lastList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanOverAllValueDataVO> sList = Collections.synchronizedList(new ArrayList<>());
		
		resList.forEach(x->{
			String typeTemp = x.getType();
			if(typeTemp.equals(OrgTypeEunm.ORG_STAGE.getKey())){
				sList.add(x);
            }else {
            	lastList.add(x);
            }
		});
		
		//排序
		if(CollectionUtils.isNotEmpty(sList)){
			List<SupplyPlanOverAllValueDataVO> sortList = sList.parallelStream().sorted((a, b) -> {
			    //分期
			    String aStageName = StrUtils.nvl(a.getName());
			    String bStageName = StrUtils.nvl(b.getName());
			    if (!aStageName.equals(bStageName)) {
			    	return ReportUtils.compareStrStartedChinaNum(aStageName, bStageName);
			    }
			    return 0;
			}).collect(Collectors.toList());
			lastList.addAll(sortList);
         }
		
		return lastList;
	}

	private BaseValueVO initYearValue() {
		BaseValueVO yearValueVO = new BaseValueVO();
		yearValueVO.setNum("0");
		yearValueVO.setSaleArea("0.00");
		yearValueVO.setAvgPrice("0");
		yearValueVO.setPrice("0");
		yearValueVO.setActualNum("0");
		yearValueVO.setActualArea("0.00");
		yearValueVO.setActualAveragePrice("0");
		yearValueVO.setActualPrice("0");
		yearValueVO.setAchievingRate("-");
		return yearValueVO;
	}
	
	private List<MonthValueVO> initMonthValue(String year) {
		List<MonthValueVO> list = new ArrayList<>();
		for(int i=1;i<=Constants.LAST_MONTH;i++) {
			String m="";
			MonthValueVO vo = new MonthValueVO();
			if(i<10) {
				m="0"+i;
			}else {
				m=i+"";
			}
			vo.setName(year+"-"+m);
			vo.setNum("0");
			vo.setSaleArea("0.00");
			vo.setAvgPrice("0");
			vo.setPrice("0");
			vo.setActualNum("0");
			vo.setActualArea("0.00");
			vo.setActualAveragePrice("0");
			vo.setActualPrice("0");
			vo.setAchievingRate("-");
			list.add(vo);
		}
		return list;
	}
	
	/**
	 * 
	 * 方法描述：1、月度动态版：
			规则： {归属月份}月动态版{版本号}-{最后更新时间}
			示例：201910月动态版V1-20191201；
			2、投资版、战规版、大定价版：
			规则：{版本类型}{版本号}-{最后更新时间}
			示例：投资版V1-20191102，战规版V3-20191102，大定价版V2-20191102
			3、预算版：
			规则：{预算年份}{全年/年中}预算版{版本号}-{最后更新时间}
			示例：2019全年预算版V1-20181212，2019全年预算版V5-20190331，
			2019年中预算版V1-20190501，2019年中预算版V5-20190831
	 * @param supplyPlanVersion
	 * @return String
	 * 创建人：yyd
	 * 创建时间：2019年12月6日 下午3:38:09
	 */
	private String prepareVersionName(SupplyPlanVersion supplyPlanVersion) {
		String versionName="";
		String versionType = supplyPlanVersion.getVersionType();
		String versionTypeName = VersionTypeEunm.getValueByKey(versionType);
		String vesionNum = supplyPlanVersion.getVersionNum();
		String lastDate = "";
		if(supplyPlanVersion.getUpdateTime() != null) {
			lastDate = LocalDateTimeUtils.formatTime(supplyPlanVersion.getUpdateTime(), "yyyyMMdd");
		}else {
			lastDate = LocalDateTimeUtils.formatTime(supplyPlanVersion.getCreateTime(), "yyyyMMdd");
		}
		if(versionType.equals(VersionTypeEunm.INVESTMENT.getKey()) || versionType.equals(VersionTypeEunm.WARPLAN.getKey())) {
			String assessmentTag="";
			Integer isAssessmentVersion = supplyPlanVersion.getIsAssessmentVersion();
			if(isAssessmentVersion != null && isAssessmentVersion.intValue() == 1) {
				assessmentTag = "(考核版)";
			}
			versionName = versionTypeName+vesionNum+"-"+lastDate+assessmentTag;
		}else if(versionType.equals(VersionTypeEunm.BUDGET.getKey())) {
			if(StrUtils.isEmpty(supplyPlanVersion.getVersionIdentify())) {
				versionName = supplyPlanVersion.getBudgetYear()+"预算版"+vesionNum+"-"+lastDate;
			}else {
				if(supplyPlanVersion.getVersionIdentify().equals(VersionIdentifyEnum.ALL_YEAR.getKey()) ||
						supplyPlanVersion.getVersionIdentify().equals(VersionIdentifyEnum.MID_YEAR.getKey())	) {
					versionName = supplyPlanVersion.getBudgetYear()+VersionIdentifyEnum.getValueByKey(supplyPlanVersion.getVersionIdentify())+"预算版"+vesionNum+"-"+lastDate;
				}else {
					versionName = supplyPlanVersion.getVersionIdentify()+vesionNum+"-"+lastDate;
				}
			}
		}else {
			String affiliationMonth = supplyPlanVersion.getAffiliationMonth();
			if(StrUtils.isNotEmpty(affiliationMonth)) {
				affiliationMonth = affiliationMonth.replace("-","");
			}
			versionName = affiliationMonth+"月动态版"+vesionNum+"-"+lastDate;
		}
		return versionName;
	}
	
	
	private String prepareVersionName(SupplyPlanVersionDto supplyPlanVersion) {
		String versionName="";
		String versionType = supplyPlanVersion.getVersionType();
		String versionTypeName = VersionTypeEunm.getValueByKey(versionType);
		String vesionNum = supplyPlanVersion.getVersionNum();
		String lastDate = "";
		if(supplyPlanVersion.getUpdateTime() != null) {
			lastDate = LocalDateTimeUtils.formatTime(supplyPlanVersion.getUpdateTime(), "yyyyMMdd");
		}else {
			lastDate = LocalDateTimeUtils.formatTime(supplyPlanVersion.getCreateTime(), "yyyyMMdd");
		}
		if(versionType.equals(VersionTypeEunm.INVESTMENT.getKey()) || versionType.equals(VersionTypeEunm.WARPLAN.getKey())) {
			String assessmentTag="";
			Integer isAssessmentVersion = supplyPlanVersion.getIsAssessmentVersion();
			if(isAssessmentVersion != null && isAssessmentVersion.intValue() == 1) {
				assessmentTag = "(考核版)";
			}
			versionName = versionTypeName+vesionNum+"-"+lastDate+assessmentTag;
		}else if(versionType.equals(VersionTypeEunm.BUDGET.getKey())) {
			if(StrUtils.isEmpty(supplyPlanVersion.getVersionIdentify())) {
				versionName = supplyPlanVersion.getBudgetYear()+"预算版"+vesionNum+"-"+lastDate;
			}else {
				if(supplyPlanVersion.getVersionIdentify().equals(VersionIdentifyEnum.ALL_YEAR.getKey()) ||
						supplyPlanVersion.getVersionIdentify().equals(VersionIdentifyEnum.MID_YEAR.getKey())	) {
					versionName = supplyPlanVersion.getBudgetYear()+VersionIdentifyEnum.getValueByKey(supplyPlanVersion.getVersionIdentify())+"预算版"+vesionNum+"-"+lastDate;
				}else {
					versionName = supplyPlanVersion.getVersionIdentify()+vesionNum+"-"+lastDate;
				}
			}
		}else {
			String affiliationMonth = supplyPlanVersion.getAffiliationMonth();
			if(StrUtils.isNotEmpty(affiliationMonth)) {
				affiliationMonth = affiliationMonth.replace("-","");
			}
			versionName = affiliationMonth+"月动态版"+vesionNum+"-"+lastDate;
		}
		return versionName;
	}
	

	private List<SupplyPlanOverAllValueDataVO> overAllVersionDetailSort(List<SupplyPlanOverAllValueDataVO> dataList) {
		List<SupplyPlanOverAllValueDataVO> sortList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanOverAllValueDataVO> groupList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanOverAllValueDataVO> batchList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanOverAllValueDataVO> productList = Collections.synchronizedList(new ArrayList<>());
		List<SupplyPlanOverAllValueDataVO> houseList = Collections.synchronizedList(new ArrayList<>());
		dataList.forEach(x->{
			String typeTemp = x.getType();
			if(typeTemp.equals(OrgTypeEunm.ORG_GROUP.getKey())){
		        groupList.add(x);
		    }else if(typeTemp.equals(OrgTypeEunm.ORG_BATCH.getKey())){
		        batchList.add(x);
		    }else if(typeTemp.equals(OrgTypeEunm.ORG_PRODUCT.getKey())) {
		        productList.add(x);
		    }else if(typeTemp.equals(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())){
		        houseList.add(x);
		    }else {
		    	sortList.add(x);
		    }
		});
		//组团
		if(CollectionUtils.isNotEmpty(groupList)){
		     groupList.sort((a, b) -> {
		         String aName = a.getName();
		         String bName = b.getName();

		         String[] aStr = aName.split("组团");
		         String[] bStr = bName.split("组团");

		         if(aStr[0].equals(Constants.PARKING_NAME)) {
		             aStr[0] = Constants.GROUP_NUM;
		         }
		         if(bStr[0].equals(Constants.PARKING_NAME)){
		             bStr[0] = Constants.GROUP_NUM;
		         }

		         String aValue = NumberEnum.getKeyByValue(aStr[0]);
		         String bValue = NumberEnum.getKeyByValue(bStr[0]);
		         if(StrUtils.isEmpty(aValue)) {
		        	return 1; 
		         }else if(StrUtils.isEmpty(bValue)) {
		        	 return -1;
		         }else if(StrUtils.isNotEmpty(aValue) && StrUtils.isNotEmpty(bValue)) {
		        	 return Integer.valueOf(aValue) - Integer.valueOf(bValue);
		         }
		         return 0;
		     });
		     sortList.addAll(groupList);
		 }
		//批次
		 if(CollectionUtils.isNotEmpty(batchList)) {
		     batchList.sort((a, b) -> {
		         String aName = a.getName();
		         String bName = b.getName();

		         String[] aStr = aName.split("批次");
		         String[] bStr = bName.split("批次");

		         String aValue = NumberEnum.getKeyByValue(aStr[0]);
		         String bValue = NumberEnum.getKeyByValue(bStr[0]);
		         if(StrUtils.isEmpty(aValue)) {
		        	return 1; 
		         }else if(StrUtils.isEmpty(bValue)) {
		        	 return -1;
		         }else if(StrUtils.isNotEmpty(aValue) && StrUtils.isNotEmpty(bValue)) {
		        	 return Integer.valueOf(aValue) - Integer.valueOf(bValue);
		         }
		         return 0;
		     });
		     sortList.addAll(batchList);
		 }
		//产品构成
		 if(CollectionUtils.isNotEmpty(productList)) {
		     productList.sort((a, b) -> {
		         String aCode = a.getCode();
		         String bCode = b.getCode();
		         aCode = StrUtils.isEmpty(aCode) ? "1" : aCode;
                 bCode = StrUtils.isEmpty(bCode) ? "-1" : bCode;
                 if(StrUtils.isEmpty(aCode)) {
 		        	return 1; 
 		         }else if(StrUtils.isEmpty(bCode)) {
 		        	 return -1;
 		         }else if(StrUtils.isNotEmpty(aCode) && StrUtils.isNotEmpty(bCode)) {
 		        	 return Integer.valueOf(aCode) - Integer.valueOf(bCode);
 		         }
 		         return 0;
		     });
		     sortList.addAll(productList);
		 }
		 sortList.addAll(houseList);
		return sortList;
	}
	
	public int getNum(String num,String flag) {
		if(StrUtils.isEmpty(num)) {
			return 0;
		}else {
			if(num.indexOf("/") < 0) {
				if(StrUtils.isEmpty(num)) {
					return 0;
				}
				return Integer.valueOf(num);
			}else {
				String rNum = num.substring(0, num.indexOf("/")).trim();
				String pNum = num.substring(num.indexOf("/")+1, num.length()).trim();
				if(flag.equals(HOUSE_KEY)) {
					if(StrUtils.isEmpty(rNum)) {
						return 0;
					}else {
						return Integer.valueOf(rNum);
					}
				}else {
					if(StrUtils.isEmpty(pNum)) {
						return 0;
					}else {
						return Integer.valueOf(pNum);
					}
				}
			}
		}
	}
	
	public BigDecimal getPrice(String price,String flag) {
		BigDecimal res = BigDecimal.ZERO;
		if(StrUtils.isEmpty(price)) {
			return res;
		}else {
			if(price.indexOf("/") < 0) {
				if(StrUtils.isEmpty(price)) {
					return res;
				}
				return new BigDecimal(price);
			}else {
				if(NumberUtils.hasMoreOne(price, "/")) {
					price = price.substring(price.indexOf("/")+1, price.length()).trim();
				}
				String rprice = price.substring(0, price.indexOf("/")).trim();
				String pprice = price.substring(price.indexOf("/")+1, price.length()).trim();
				if(flag.equals(HOUSE_KEY)) {
					if(StrUtils.isEmpty(rprice)) {
						return res;
					}else {
						if(rprice.indexOf(",") > 0) {
							rprice = rprice.replaceAll(",", "");
						}
						return new BigDecimal(rprice);
					}
				}else {
					if(StrUtils.isEmpty(pprice)) {
						return res;
					}else {
						if(pprice.indexOf(",") > 0) {
							pprice = pprice.replaceAll(",", "");
						}
						return new BigDecimal(pprice);
					}
				}
			}
		}
	}
	
	private SupplyPlanOverAllValueDataVO getProjectLevel(String year) {
		SupplyPlanOverAllValueDataVO vo =  new SupplyPlanOverAllValueDataVO();
		vo.setOverAllValueVO(new BaseValueVO());
		vo.setYearValueVO(new BaseValueVO());
		vo.setMonthValue(initMonthValue(year));
		return vo;
	}
	
	private void setMonthData(List<SupplyPlanVersionDetail> list,MonthValueVO monthValueVO,String id,String versionType) {
		if(CollectionUtils.isNotEmpty(list)) {
			for(SupplyPlanVersionDetail obj : list) {
				if(obj.getId().equals(id)) {
					monthValueVO.setNum(EmptyUtils.handleNumNullValue(obj.getNums()));
					monthValueVO.setSaleArea(EmptyUtils.handleAreaNullValue(obj.getSaleArea()));
					monthValueVO.setAvgPrice(EmptyUtils.handleAvgNullValue2(obj.getAvgPrice()));
					monthValueVO.setPrice(EmptyUtils.handlePriceNullValue2(obj.getPrice()));
					if(!versionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
						monthValueVO.setActualNum(EmptyUtils.handleNumNullValue(obj.getNumsActual()));
						monthValueVO.setActualArea(EmptyUtils.handleAreaNullValue(obj.getAreaActual()));
						monthValueVO.setActualAveragePrice(EmptyUtils.handleAvgNullValue2(obj.getAvgPriceActual()));
						monthValueVO.setActualPrice(EmptyUtils.handlePriceNullValue2(obj.getPriceActual()));
						BigDecimal planPrice = EmptyUtils.getPrice(obj.getPrice());
						BigDecimal actualPrice = EmptyUtils.getPrice(obj.getPriceActual());
						
						if(planPrice == null || planPrice.compareTo(BigDecimal.ZERO) == 0) {
							monthValueVO.setAchievingRate("-");
						}else {
							monthValueVO.setAchievingRate(StrUtils.divide(actualPrice+"",planPrice+"",4));
						}
					}
				}
			}
		}
	}

	private List<MonthExcelValueVO> getMonthExcelValue(String year) {
		List<MonthExcelValueVO> list = new ArrayList<>();
		for(int i=1;i<=Constants.LAST_MONTH;i++) {
			String m="";
			MonthExcelValueVO vo = new MonthExcelValueVO();
			if(i<10) {
				m="0"+i;
			}else {
				m=i+"";
			}
			vo.setMonth(year+"-"+m);
			list.add(vo);
		}
		return list;
	}
	
	private List<ProjectMonthExcelValueVO> getProMonthExcelValue(String year) {
		List<ProjectMonthExcelValueVO> list = new ArrayList<>();
		for(int i=1;i<=Constants.LAST_MONTH;i++) {
			String m="";
			ProjectMonthExcelValueVO vo = new ProjectMonthExcelValueVO();
			if(i<10) {
				m="0"+i;
			}else {
				m=i+"";
			}
			vo.setMonth(year+"-"+m);
			list.add(vo);
		}
		return list;
	}
	
	/**
	 * 供货版本对比
	 */
	@Override
	public R versionCompareDetail(String apiVersion, String projectId,String deadline) {
		List<SupplyPlanVersionCompareVO> list = supplyPlanVersionCompareService.selectVersionCompareData(projectId,deadline);
		return ok(list);
	}
	
	/**
	 * 
	 * 方法描述：保存操作日志
	 * @param module 模块
	 * @param title 标题
	 * @param content 日志内容
	 * @return boolean
	 * 创建人：yyd
	 * 创建时间：2019年9月24日 上午9:24:58
	 */
	private boolean saveLog(String module,String title,String content) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		String userName = getOperator().getAlias();
		SysLogBO bo = new SysLogBO();
		bo.setEvent(LogEventEnum.BROWSE);
    	bo.setSource(LogSrcEnum.PC);
    	bo.setIp(WebUtils.getIpAddr(request));
    	bo.setUrl(WebUtils.getUrl(request));
    	bo.setModule(module);
    	bo.setTitle(title);
    	bo.setContent(content);
    	bo.setType(LogTypeEnum.ZERO.getKey());
    	bo.setIsSuccess(IsSuccessEnum.SUCCESS.getKey());
        return sysLogService.add(bo,userName);
	}

	@Override
	public R sendToDoMsg(String apiVersion, String projectId, String versionId) {
		supplyPlanVersionService.sendToDoMsg(projectId,versionId,1);
		return ok();
	}
	
	@Override
	public R sendSupplyConfirmTask(String apiVersion) {
		supplyPlanTasks.sendSupplyConfirmTask();
		return ok();
	}
	
	@Override
	public R cleanToDo(String apiVersion, String projectId) {
		IdmUser user = getOperator();
		supplyConfirmRecordService.cleanToDo(projectId,user);
		return ok();
	}
	
	@Override
	public R closeSupplyConfirmTask(String apiVersion) {
		supplyPlanTasks.handleOverdueUnconfirmed();
		return ok();
	}
	
	/**
	 * 
	 * @Description：检查项目是否需要确认供货
	 * @author：yyd
	 * @date：2020年3月6日 下午5:20:59
	 */
	public boolean isNeedConfirmSupply(String projectId,String affiliationMonth) {
		return supplyPlanVersionService.isNeedConfirmSupply(projectId, affiliationMonth);
	}

	@Override
	public R handleConfirmSupplyData(String apiVersion,String projectFid,String isSign,String isAll,String month) {
		supplyPlanVersionService.handleConfirmSupplyData(month,projectFid,isSign,isAll);
		return ok();
	}
}
